在现代处理器架构中,向量处理能力已成为衡量计算性能的关键指标。Arm的可伸缩向量扩展(Scalable Vector Extension, SVE)通过引入可变长度向量寄存器,为数据并行处理提供了更灵活的支持。作为SVE指令集的重要组成部分,存储指令的设计直接影响着向量化计算的效率。
SVE存储指令家族包含多种变体,主要特点包括:
这些指令在机器学习推理、科学计算、图像处理等场景中表现出色。例如在卷积神经网络中,ST4H指令可以高效存储中间特征图,而STNT1B则适合处理大型权重矩阵的更新。
ST4H指令执行连续的四半字结构存储操作,其汇编语法有两种形式:
assembly复制// 立即数偏移版本
ST4H { <Zt1>.H, <Zt2>.H, <Zt3>.H, <Zt4>.H }, <Pg>, [<Xn|SP>{, #<imm>, MUL VL}]
// 标量寄存器索引版本
ST4H { <Zt1>.H, <Zt2>.H, <Zt3>.H, <Zt4>.H }, <Pg>, [<Xn|SP>, <Xm>, LSL #1]
指令编码关键字段:
Zt:基础向量寄存器编号(实际使用Zt, Zt+1, Zt+2, Zt+3四个寄存器)Pg:谓词寄存器(P0-P7)Rn:基址寄存器(通用寄存器或栈指针)imm4:立即数偏移(-32到28,4的倍数)Rm:索引寄存器(标量版本)ST4H指令执行流程可分为以下几个阶段:
初始化检查:
地址生成:
pseudocode复制base = (n == 31) ? SP() : X[n];
// 立即数版本
addr = base + (offset * elements * 4 * (esize/8))
// 标量版本
addr = base + (X[m] * (esize/8))
数据准备:
存储循环:
pseudocode复制for e = 0 to elements-1
for r = 0 to 3
if 谓词有效 then
Mem[addr] = Zt+r[e*esize : (e+1)*esize]
addr += esize/8
考虑图像处理中的RGB565像素存储场景:
c复制// C语言示例:存储RGB565像素块
void store_rgb565(uint16_t* dst, svuint16x4_t pixels, svbool_t mask) {
asm volatile(
"st4h {%0.h, %1.h, %2.h, %3.h}, %4, [%5]"
:: "w"(pixels.val[0]), "w"(pixels.val[1]),
"w"(pixels.val[2]), "w"(pixels.val[3]),
"w"(mask), "r"(dst)
);
}
非临时存储(Non-temporal Store)是一种优化技术,它向处理器提示:
与传统存储相比的优势:
STNT1B指令有四种主要变体:
单寄存器+立即数偏移
assembly复制STNT1B { <Zt>.B }, <Pg>, [<Xn|SP>{, #<imm>, MUL VL}]
单寄存器+标量索引
assembly复制STNT1B { <Zt>.B }, <Pg>, [<Xn|SP>, <Xm>]
连续寄存器+立即数偏移
assembly复制STNT1B { <Zt1>.B-<Zt2>.B }, <PNg>, [<Xn|SP>{, #<imm>, MUL VL}]
连续寄存器+标量索引
assembly复制STNT1B { <Zt1>.B-<Zt4>.B }, <PNg>, [<Xn|SP>, <Xm>]
谓词处理:
地址生成:
base + offset * nreg * elementsbase + X[m] * esize/8数据流:
pseudocode复制for r = 0 to nreg-1
src = Z[transfer+r]
for e = 0 to elements-1
if 谓词有效 then
Mem[addr] = src[e*esize : (e+1)*esize]
addr += esize/8
在矩阵转置中的应用示例:
c复制void transpose_store(uint8_t* dst, svuint8_t row, svbool_t mask) {
asm volatile(
"stnt1b %0.b, %1, [%2]"
:: "w"(row), "w"(mask), "r"(dst)
: "memory"
);
}
优化要点:
SVE提供两种谓词寄存器:
关键谓词操作函数:
pseudocode复制function ActivePredicateElement(mask, e, esize)
return mask[e * (PL/elements)] == 1
function CounterToPredicate(counter)
// 将计数器值转换为位掩码
return ExpandCounter(counter)
典型谓词执行流程:
AccessDescriptor关键字段:
| 字段名 | 取值 | 作用 |
|---|---|---|
| MemOp | STORE | 存储操作类型 |
| nontemporal | TRUE/FALSE | 是否非临时 |
| contiguous | TRUE/FALSE | 是否连续访问 |
| predicated | TRUE/FALSE | 是否谓词化 |
| tagchecked | TRUE/FALSE | 是否检查内存标签 |
地址计算通用公式:
code复制AddressAdd(base, offset, accdesc):
if accdesc.contiguous then
return base + offset
else
return GenerateNonContigAddr(base, offset)
栈指针对齐检查:
pseudocode复制procedure CheckSPAlignment()
if SP % 16 != 0 then
GenerateAlignmentFault()
GCC风格内联汇编示例:
c复制void sve_store4(uint16_t* dst, svuint16x4_t data, svbool_t pg) {
asm volatile(
"st4h {%0.h, %1.h, %2.h, %3.h}, %4, [%5]"
:: "w"(data.val[0]), "w"(data.val[1]),
"w"(data.val[2]), "w"(data.val[3]),
"w"(pg), "r"(dst)
: "memory"
);
}
循环展开策略:
数据预取:
c复制svprfd(pg, addr, SV_PLDL1KEEP);
谓词优化:
对齐错误:
谓词失效:
性能下降:
典型处理流程:
矩阵乘法存储阶段:
c复制for (int i = 0; i < M; i += VL/32) {
svbool_t pg = svwhilelt_b32(i, M);
svstnt1b(pg, &C[i*N + j], result);
}
压缩算法存储模式:
| 特性 | ST4H | STNT1B |
|---|---|---|
| 数据宽度 | 半字(16位) | 字节(8位) |
| 结构数量 | 固定4个 | 1/2/4可选 |
| 临时性 | 常规存储 | 非临时存储 |
| 适用场景 | 结构化数据 | 流式数据 |
选择建议:
存储指令的流水线特性:
优化策略:
SVE2增强特性:
在实际工程实践中,合理运用这些存储指令通常能获得2-3倍的内存带宽提升。特别是在处理不规则数据结构时,谓词与非临时存储的组合使用可以显著降低不必要的内存访问开销。