使用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%

相关推荐
2401_892070981 天前
【Linux C++ 日志系统实战】LogFile 日志文件管理核心:滚动策略、线程安全与方法全解析
linux·c++·日志系统·日志滚动
lwx9148521 天前
Linux-Shell算术运算
linux·运维·服务器
somi71 天前
ARM-驱动-02-Linux 内核开发环境搭建与编译
linux·运维·arm开发
双份浓缩馥芮白1 天前
【Docker】Linux 迁移 docker 目录(软链接)
linux·docker
黄昏晓x1 天前
Linux ---- UDP和TCP
linux·tcp/ip·udp
路溪非溪1 天前
Linux驱动开发中的常用接口总结(一)
linux·运维·驱动开发
此刻觐神1 天前
IMX6ULL开发板学习-01(Linux文件目录和目录相关命令)
linux·服务器·学习
2401_892070981 天前
【Linux C++ 日志系统实战】高性能文件写入 AppendFile 核心方法解析
linux·c++·日志系统·文件写对象
航Hang*1 天前
第3章:Linux系统安全管理——第2节:部署代理服务
linux·运维·服务器·开发语言·笔记·系统安全
-ONLY-¥1 天前
PostgreSQL运维全攻略:从基础操作到远程配置
linux