rvv 相关配置参数说明

前言/引言

今天面试中遇到了一些关于rvv的参数相关的问题,本身比较一知半解,所以还是挺尴尬的,说自己会写rvv。所以这里对于常用的一些参数进行记录。

基础配置参数

按照在写rvvkernel中遇到的来说明,主要有一下几个:

  • vl
    • 向量长度,通常是通过__riscv_vsetvl_e32m1来自动获取当前一个向量的元素数
  • vlen
    • 和硬件相关的单个向量寄存器宽度,128、256、512
  • elen
    • 硬件支持的最大元素宽度:32、64等
  • sew
    • 根据dtype来确定,fp32: sew=32 ;fp16:sew=16
  • lmul
    • 通过mX的x来确定具体使用的向量寄存器数量
  • vlmax
    - 根据前面三者计算得到:$vlmax = (vlen*lmul)/ seq$,

RVV内在函数核心标记总览

标记字母 在函数名中的位置 全称/含义 功能描述 示例
v 前缀 Vector 标识这是一个向量操作。 vaddvle32
l / s v之后 Load / Store 表示内存操作是加载(读内存)还是存储(写内存)。 vle32 (加载), vse32 (存储)
s le之间 Strided 表示使用显式步长的非连续内存访问。 **vlse32**vsse32
x le之间 Indexed 表示使用向量寄存器中的索引进行散状(Gather)或散开(Scatter)访问。 vlxei32vsxei32
e l/s之后 Element width 指示内存中单个数据元素的宽度(位数)。紧随其后的数字即为宽度。 vle**32** (32位元素)
m e{width}之后 Machine register LMUL 指示操作使用的向量寄存器组(LMUL)。数字为分组因子。 vadd.**v**v**i32m1** (使用LMUL=1)
u / f e{width}之后 Unsigned / Float 指示操作数的数据类型是无符号整数或浮点数。 vle32**u** (无符号加载), vle32**f** (浮点加载)
v / x / i 运算操作名之后 Operand Source 指示操作数的来源:v(向量), x(标量), i(立即数)。 vadd.**vv** (向量+向量), vadd.**vx** (向量+标量), vadd.**vi** (向量+立即数)
m 操作数来源之后 Mask 表示这是一个掩码操作,使用v0作为谓词掩码。 vadd.vv **m** (掩码加法)
t 指令后缀 Tied Operand 表示目的操作数与第一个源操作数是同一个寄存器(融合操作数)。常用于归约等操作。 vredsum.vs **t**

高级应用

1. 内存操作三剑客
这三种加载指令覆盖了所有主流的内存访问模式,是编程的核心:

  • vle32: 连续访问。效率最高,是基础。
  • vlse32: 固定步长访问。用于处理矩阵行列、结构体数组。
  • vlxei32: 索引访问(Gather)。功能最强大也最灵活,允许通过一个索引向量从任意地址收集数据,适合处理完全不规则的数据(如哈希表、稀疏矩阵的非零元)。
    2. 掩码操作 (m)
    这是实现条件向量化和循环尾部处理的关键。例如,vmadd.vv 表示 “在掩码为1的通道上,执行乘法累加”,这可以避免对数组边界外或不符合条件的元素进行操作。

3. 归约与融合操作数 (t)
像 vredsum.vs 这样的归约操作,会将一个向量“压缩”成一个标量。标记 t 表示其目的标量寄存器与一个源向量寄存器是同一个物理寄存器(被“绑定”了),这种设计优化了寄存器文件的压力。