使用rvv优化rms_norm

优化内容

核心优化点:

将一个循环规约变成rvv形式的

原代码:

cpp 复制代码
ggml_float sum = 0.0;
for (int64_t i00 = 0; i00 < ne00; i00++) {
    sum += (ggml_float)(x[i00] * x[i00]);
}

const float mean = sum/ne00;

优化后:

cpp 复制代码
size_t vl = __riscv_vsetvl_e32m4(ne00);
vfloat64m8_t sum_vec = __riscv_vfmv_v_f_f64m8(0.0, __riscv_vsetvl_e64m8(ne00));

int64_t i00 = 0;
for (; i00 <= ne00 - (int64_t)vl; i00 += (int64_t)vl) {
   vl = __riscv_vsetvl_e32m4(ne00 - i00);
   
   // 加载fp32数据
   vfloat32m4_t x_vec_f32 = __riscv_vle32_v_f32m4(&x[i00], vl);
   
   // 将fp32扩展为fp64 - 使用正确的类型转换
   vfloat64m8_t x_vec_f64 = __riscv_vfwcvt_f_f_v_f64m8(x_vec_f32, vl);
   
   // 在fp64精度下计算平方
   vfloat64m8_t square_vec = __riscv_vfmul_vv_f64m8(x_vec_f64, x_vec_f64, vl);
   
   // fp64精度累加
   sum_vec = __riscv_vfadd_vv_f64m8(sum_vec, square_vec, vl);
}

// 规约求和(fp64精度)
vfloat64m1_t vec_sum = __riscv_vfmv_v_f_f64m1(0.0f, vl);
vec_sum = __riscv_vfredusum_vs_f64m8_f64m1(sum_vec, vec_sum, vl);

double sum = __riscv_vfmv_f_s_f64m1_f64(vec_sum);

效果评估

不适用RVV

开启RVV,但使用redosum(效率较低)

开启RVV,使用redusum

开RVV基础上使用redusum同时使用float32进行

使用到rms_norm的部分,主要包含在prompt eval 和 eval两个阶段,可以看到,二者对应的时间也是在减小的,优化比在0.12%和0.31%

相关推荐
飞凌嵌入式3 分钟前
解析一下面向教育领域的RV1126B\RK3506B\RK3576开发板
linux·人工智能
Xの哲學5 分钟前
Linux io_uring 深度剖析: 重新定义高性能I/O的架构革命
linux·服务器·网络·算法·边缘计算
菜择贰1 小时前
在linux(wayland)中禁用键盘
linux·运维·chrome
oMcLin1 小时前
如何在 Manjaro Linux 上通过配置systemd服务管理,提升微服务架构的启动速度与资源效率
linux·微服务·架构
Kira Skyler1 小时前
bpftool -S 签名功能实现解析
linux
小杰帅气2 小时前
进程优先级与切换调度
linux·运维·服务器
方便面不加香菜2 小时前
Linux基本指令(1)
linux
济6172 小时前
linux(第十四期)--Uboot移植(1)-- Ubuntu20.04
linux
奋斗的阿狸_19862 小时前
键盘组合键监听与 xterm 唤醒程序
linux·运维·服务器
小张成长计划..2 小时前
【linux】2:linux权限的概念
linux·运维·服务器