- 实验文档参考此处。
- 实验代码如下:
size_t vl_max = __riscv_vsetvlmax_e8m1();
int stride = 4;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
int32_t sum = 0;
for (int kk = 0; kk < k * stride; kk += vl_max) {
size_t current_vl = __riscv_vsetvl_e8m1(k * stride - kk);
// 跳步加载
vuint8m1_t va = __riscv_vlse8_v_u8m1(&A[i * k * stride + kk], 1, current_vl);
vint8m1_t vb = __riscv_vlse8_v_i8m1(&B[j * k * stride + kk], 1, current_vl);
vint16m2_t vprod_ext1 = __riscv_vwmulsu_vv_i16m2(vb, va, current_vl);
vint32m4_t vprod_ext = __riscv_vsext_vf2_i32m4(vprod_ext1, current_vl);
// 此处注意,为了测试时间所以外层有1000次循环,如果需要printf的话需要修改打印次数
// if(i == 0 && j == 0) {
// printf("%d\n", vl_max);
// print_vector(vprod_ext, current_vl);
// }
// 规约求和
vint32m1_t v_zero = __riscv_vmv_v_x_i32m1(0, current_vl);
vint32m1_t v_sum = __riscv_vredsum_vs_i32m4_i32m1(vprod_ext, v_zero, current_vl);
sum += __riscv_vmv_x_s_i32m1_i32(v_sum);
}
C[i * n + j] = sum;
}
}
- 在开发过程中我出现bug的两处:
- 没有考虑到A和B矩阵的列数是K * 4,也即naive实现里面k * 4作为循环跳出条件的原因。
- 没有考虑到lse这种加载方式中第二个参数stride的作用,造成了重复读取(设为0)。
-
同时推荐使用printf的方式对rvv用到的一些向量进行打印。
-
测试结果:
Baseline: 34205 ms
Optimized: 10575 ms
Speedup: 3.23452x -
使用直接load的方式加载
测试结果:
Baseline: 34222 ms
Optimized: 4713 ms
Speedup: 7.26119x
证明对于连续数据使用不带stride的读写会显著优于带stride的读写。

5821

被折叠的 条评论
为什么被折叠?



