__riscv_vlse32_v_f32m4 是 RISC-V 向量扩展(RVV)Intrinsics 里用于 跨步(strided)加载 32-bit 浮点数据 到向量寄存器的函数,其原型与要点如下:


1. 原型(GCC/Clang 内置)

1
2
3
4
5
6
#include <riscv_vector.h>

vfloat32m4_t __riscv_vlse32_v_f32m4(
const float *base, // 基地址 rs1
ptrdiff_t stride, // 字节步幅 rs2(可为负)
size_t vl); // 向量长度
  • 返回vfloat32m4_t 类型的向量寄存器组,最多可持有 vlfloat 元素。
  • 寻址方式:第 i 个元素地址 = base + i * stride(字节)。
  • stride 可为负,因此既能正向也能反向跨步加载。
  • vlvsetvl_e32m4(n) 计算得到,表示“当前硬件一次能处理的元素数”。

2. 功能与场景

  • 非连续(间隔)内存中的 float 加载到向量寄存器,用于后续向量计算。
  • 典型场景:
    – 二维/三维数组按行/列访问(列主序时列间隔 ≠ 1)
    – 稀疏矩阵中固定步长的“切片”
    – 信号处理中的降采样(stride = 采样间隔)

3. 最小示例

1
2
3
4
5
6
7
8
9
10
float a[100] = {...};
size_t n = 20;
ptrdiff_t col_stride = sizeof(float) * 5; // 每 5 个 float 取 1 个

size_t vl;
for (size_t i = 0; i < n; i += vl) {
vl = vsetvl_e32m4(n - i);
vfloat32m4_t vec = __riscv_vlse32_v_f32m4(&a[i], col_stride, vl);
// ... 后续向量计算
}

4. 与连续加载对比

连续加载 跨步加载
vle32_v_f32m4(ptr, vl) vlse32_v_f32m4(ptr, stride, vl)
地址 = ptr + i 地址 = ptr + i * stride
带宽最高 带宽降低,但支持非连续布局

5. 注意事项

  1. stride 以字节为单位,不是元素个数。
  2. 若 stride = 0,则退化成“广播”同一地址的值(可用于填充向量)。
  3. 当 stride < 0 时,base 应指向 末元素,实现反向加载。
  4. 对齐:RVV 不对跨步加载做地址对齐要求,但 对齐到元素大小 可提升性能。

一句话总结
__riscv_vlse32_v_f32m4 就是 RVV 的 向量跨步加载 指令 vlse32.v 的 C 语言 Intrinsic 封装,用来把 间隔排布 的 32-bit 浮点数据一次性搬进向量寄存器,是稀疏/二维数据向量化的关键入口。