在 ARM SVE(Scalable Vector Extension) intrinsics 指令集中,svld1_u8 是基础的单元素宽度向量加载指令,用于从内存中连续加载无符号 8 位整数(uint8_t)到 SVE 向量中,是处理字节级数据(如图像像素、字符串、传感器数据等)的常用指令。
svuint8_t svld1_u8(
svbool_t pg, // 掩码:指示哪些元素需要加载
const uint8_t *base // 基地址:内存中连续数据的起始地址
);
-
pg(predicate mask)
类型为 svbool_t 的掩码向量,用于标记向量中哪些位置需要加载有效数据。只有掩码位为1的元素会从内存中读取,其他位置的结果未定义(实际使用中通常忽略或填充 0)。
- 掩码的长度由当前硬件的 SVE 向量宽度决定(例如 128 位向量对应 16 个 8 位元素,掩码含 16 个 bit)。
-
base
指向内存中uint8_t类型数据的基地址,指令会从该地址开始连续加载数据,加载的元素数量等于掩码中1的位数(通常是整个向量长度)。
svld1_u8 的核心是从内存连续地址加载无符号 8 位整数到 SVE 向量,并通过掩码控制有效元素。其中 “ld1” 表示 “load 1-element”,即每次加载单个元素宽度(8 位)的数据,适用于最基础的连续内存访问场景。
- 例如:若硬件支持 128 位 SVE 向量(可存储 16 个
uint8_t),svld1_u8 会从base开始连续加载 16 个字节(base到base+15),存入向量的 16 个 lane 中,掩码pg中为1的 lane 会保留加载值。
假设需要对一个uint8_t数组的所有元素进行累加(如计算图像像素的总和),使用svld1_u8实现向量化加载:
#include <arm_sve.h>
#include <stdint.h>
uint64_t sum_uint8_array(const uint8_t* arr, size_t len) {
uint64_t total = 0;
size_t i = 0;
// 获取当前硬件支持的8位元素最大向量长度(如16,对应128位向量)
svcount_t vl = svcntb();
// 生成初始掩码:i < len 时,前min(vl, len-i)个元素有效
svbool_t pg = svwhilelt_b8(i, len);
while (svptest_any(svptrue_b8(), pg)) { // 掩码有有效元素时继续循环
// 从arr+i位置连续加载uint8_t到向量,仅加载掩码pg为1的元素
svuint8_t vec = svld1_u8(pg, arr + i);
// 累加向量中有效元素的和(仅掩码为1的元素参与)
total += svaddv_u8(pg, vec);
// 更新循环变量(i += 本次加载的元素数,即vl)
i += vl;
// 更新掩码(判断剩余元素是否需要加载)
pg = svwhilelt_b8(i, len);
}
return total;
}
-
向量长度的伸缩性
SVE 的向量长度是硬件相关的(如 128 位、256 位等),svld1_u8 会自动适配当前硬件的向量宽度,无需手动指定长度(通过svcntb()可获取 8 位元素的最大向量长度)。
-
掩码的作用
当数组长度len不是向量长度的整数倍时,掩码pg会标记最后一批需要加载的元素(例如len=20,vl=16,则最后一次循环的掩码仅前 4 位为 1),避免越界访问。
-
与内存布局的配合
svld1_u8 要求数据在内存中连续存储,且支持非对齐访问(无需严格对齐到向量宽度),但对齐到 8 字节(uint64_t)边界可提升性能。
-
与其他加载指令的区别
svld1_u8 是连续加载,适用于数组、缓冲区等连续存储的 8 位数据;
- 若需加载非连续数据(如通过索引访问),需使用
svld1_gather系列指令;
- 若需指定偏移量或部分加载,可使用
svldl_u8(带长度和偏移的加载)。
svld1_u8 是 SVE 中处理连续内存无符号 8 位整数的基础加载指令,通过掩码控制有效元素,自动适配硬件向量长度,广泛用于图像处理、字节流解析、传感器数据读取等场景。其设计简洁高效,是构建高性能 8 位数据处理逻辑的核心工具。