在Arm架构的可伸缩向量扩展(Scalable Vector Extension, SVE)中,向量加载指令是实现高效数据搬运的核心。与传统的SIMD指令集不同,SVE引入了谓词执行(Predication)机制,通过谓词寄存器(Pg)控制哪些向量元素需要真正执行操作。这种设计在保持高性能的同时,提供了更灵活的数据处理能力。
LD1SW和LD1W是SVE中专门用于加载字(32位)数据的指令:
这两条指令的共同特点是:
提示:SVE的谓词执行机制是其区别于传统SIMD的关键特性之一。它允许程序员只处理实际需要的数据元素,避免了对填充数据或边界条件的特殊处理,这在处理不规则数据时尤其有用。
LD1SW指令的基本语法格式为:
assembly复制LD1SW { <Zt>.D }, <Pg>/Z, [<Zn>.D{, #<imm>}]
指令编码的关键字段包括:
Zt:目标向量寄存器,用于存储加载的数据Pg:谓词寄存器,控制哪些元素需要加载Zn:基址向量寄存器,提供内存地址基址imm:立即数偏移量(可选),必须是4的倍数,范围0-124指令编码的二进制格式如下:
code复制31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
1 1 0 0 0 1 0 1 0 0 1 imm5 1 0 0 Pg Zn Zt msz<1>msz<0> U ff
LD1SW指令执行以下操作:
LD1SW特别适合处理以下类型的数据:
例如,在图像处理中处理有符号像素值时:
assembly复制// 假设Z0包含一组内存地址,P0是谓词寄存器
LD1SW { Z1.D }, P0/Z, [Z0.D, #8] // 从Z0指定的地址+8处加载有符号字数据
LD1W指令比LD1SW更加灵活,提供了多种寻址模式:
标量基址+立即数偏移:
assembly复制LD1W { <Zt>.S }, <Pg>/Z, [<Xn|SP>{, #<imm>, MUL VL}]
标量基址+标量索引:
assembly复制LD1W { <Zt>.S }, <Pg>/Z, [<Xn|SP>, <Xm>, LSL #2]
标量基址+向量索引:
assembly复制LD1W { <Zt>.D }, <Pg>/Z, [<Xn|SP>, <Zm>.D, LSL #2]
向量基址+立即数偏移:
assembly复制LD1W { <Zt>.D }, <Pg>/Z, [<Zn>.D{, #<imm>}]
LD1W根据目标寄存器类型支持两种元素大小:
32位元素(.S):
assembly复制LD1W { Z0.S }, P0/Z, [X0] // 加载到32位元素
64位元素(.D):
assembly复制LD1W { Z0.D }, P0/Z, [X0] // 加载到64位元素
对齐访问:
谓词使用:
assembly复制LD1W { Z0.S }, P0/Z, [X0] // 好的:明确使用/Z
LD1W { Z0.S }, P0, [X0] // 避免:缺少/Z可能引起混淆
循环展开:
SVE的谓词执行通过以下步骤实现:
谓词寄存器解码:
元素活跃性检查:
pseudocode复制for e = 0 to elements-1
if ElemP[mask, e, esize] == '1' then
// 处理活跃元素
else
// 跳过非活跃元素
错误处理:
典型的向量加载操作包含以下步骤:
地址生成:
内存访问:
数据写入:
SVE向量加载的异常处理特点:
活跃元素:
非活跃元素:
MTE扩展:
在3×3卷积核应用中:
assembly复制// 假设X0指向图像数据,X1指向卷积核
// 加载中心行
LD1W { Z0.S }, P0/Z, [X0, #4] // 中心像素
LD1W { Z1.S }, P0/Z, [X0, #0] // 左侧像素
LD1W { Z2.S }, P0/Z, [X0, #8] // 右侧像素
// 加载上下行(省略部分代码)
// 向量化乘法累加
FMUL Z1, Z1, Z10 // 乘以核系数
FMLA Z0, Z2, Z11 // 累加其他像素贡献
处理稀疏向量时:
assembly复制// 假设Z0包含非零元素地址,P0标记有效元素
LD1W { Z1.D }, P0/Z, [Z0.D] // 只加载有效元素
// 后续进行向量化计算
32位到64位扩展:
assembly复制// 无符号扩展
LD1W { Z0.D }, P0/Z, [X0] // 自动零扩展
// 有符号扩展需要使用LD1SW
LD1SW { Z1.D }, P0/Z, [X1]
向量长度:
内存访问模式:
谓词利用率:
对齐错误:
谓词错误:
向量长度不匹配:
地址生成优化:
循环控制:
assembly复制// 好的实践:利用SVE自动处理剩余元素
while elements > 0 do
LD1W { Z0.S }, P0/Z, [X0], #(VL/8)
// 处理数据
sub elements, elements, (VL/32)
数据预取:
| 特性 | SVE (LD1W/LD1SW) | 传统SIMD (NEON) |
|---|---|---|
| 向量长度 | 可伸缩(128-2048位) | 固定(128位) |
| 谓词执行 | 支持 | 不支持 |
| 寻址模式 | 更丰富 | 较简单 |
| 元素大小处理 | 更灵活 | 固定 |
优势:
劣势:
LD1W的向量索引模式类似于Gather操作,但:
GCC风格内联汇编示例:
c复制void load_vector(uint32_t *ptr, svuint32_t *out, svbool_t pg) {
asm volatile(
"ld1w {%0.s}, %1/z, [%2]\n"
: "=w"(*out)
: "w"(pg), "r"(ptr)
);
}
Arm提供的C语言内在函数:
c复制#include <arm_sve.h>
svuint32_t svld1uw_u32(svbool_t pg, const uint32_t *base);
svint32_t svld1sw_s32(svbool_t pg, const int32_t *base);
Arm DS-5:
perf:
LLVM-MCA: