提问人:Alex 提问时间:11/7/2023 最后编辑:Alex 更新时间:11/9/2023 访问量:92
在 RISC-V RVV 0.7.1 中屏蔽 CSR SpMV 的单个行
Masking individual rows for CSR SpMV in RISC-V RVV 0.7.1
问:
编辑:我已经将我的问题重新表述为更有成效的东西,并将在下面提供答案。这个问题的旧版本仍然在下面。
我正在RVV 0.7.1中为CSR格式实现优化的SpMV内核。在 C 语言中,SpMV 可以这样实现:
for (int i = 0; i < numRows; i++)
for (int j = rowPtr[i]; j < rowPtr[i+1]; j++)
y[i] += val[j] * x[colIdx[j]];
矢量化最初很简单,通过加载 ,使用它来执行 的索引加载,加载和乘以两者。在此之后,必须在每一行中执行约简和 (),将其中的所有乘积相加并将它们存储在 的相应索引中。挑战在于从 创建掩码,以便只有属于给定行的元素在每次缩减时处于活动状态。coldIdx
x
val
v{f}redsum.vs
y
rowPtr
我最初的想法(应该提供有关原始问题的上下文)是使用 中的索引将 1 放在向量寄存器的相应元素中,然后使用 和 元素移位创建一个包含每个元素所属行的寄存器。然而,这显然是不可行的。rowPtr
viota
如何构建所需的蒙版?
老问题
我正在尝试使用 RISC-V 矢量扩展 (0.7.1) 来创建基于索引数组的掩码寄存器。例如,采用以下索引数组 idx array
。目标是使用其中存在的索引将 1 放入相应的掩码元素中,如下面的掩码
所示:
idx array | 0 2 3 4 4 6 8
elem idx | 0 1 2 3 4 5 6 7 8
mask | 1 0 1 1 1 0 1 0 1
起初我错误地查看了 vrgather.vx
指令,但它并没有完全按照我想要的方式进行,因为它填充了所有元素。我希望代码也非常高性能,所以如果可能的话,它主要由向量指令组成,那将是理想的。如果有人能为我指出正确的方向,我将不胜感激。
答:
解决方案的功劳归功于骆驼-cdr!
采用以下数组:rowPtr
0 2 3 5 7
让我们考虑第三次迭代 (),它应该更具说明性。目标是实现以下掩码,启用元素 3 和 4:[3,5[
00011000
第一步是将每个元素的索引写入向量。这样,我们可以使用两次(如果相等,则设置掩码),带有元素和 of,这将产生两个寄存器,其中一个在元素中或:vid
vmseq
i
i+1
rowPtr
rowPtr[i]
rowPtr[i+1]
idx | 01234567
i | 00010000
i+1 | 00000100
然后,我们可以在两者上使用 (set-before-first),它将所有位设置在第一个活动掩码位之前。通过对两者进行异或运算,我们得到最终所需的掩码:vmsbf.m
sbf i | 11100000
sbf i+1 | 11111000
xor | 00011000
通过遍历和重复此操作,可以为每一行的元素生成一个掩码。简而言之,我们可以将此操作编写为:rowPtr
vmxor(vmsbf(vmseq(vid,rowPtr[i])), vmsbf(vmseq(vid,rowPtr[i+1])))
下一个:根据矩阵对矩阵中的元素进行排序
评论
redsum
viota
for i from rOff[row] to rOff[row+1]: sum += vals[i] * x[cols[i]];
rOff[row] to rOff[row+1]
begin=rOff[row]
end=rOff[row+1]
vmxor(vmsbf(vmseq(vid,begin)), vmsif(vmseq(vid,end)))
vmsbf
vmsif
begin
end - begin
vmsbf
vmsif