Qualcomm Hexagon平台乘累加(MAC)循环的DSP优化方案咨询
Hexagon DSP MAC循环优化实现建议
针对你的需求,提供三种可落地的实现方案,覆盖C intrinsics、汇编两种实现形式:
1. 标量4倍展开实现(C语言,无平台强依赖)
不需要调用专用intrinsics,利用Hexagon标量单元原生支持的64位内存加载能力完成4个16位数据的批量读取,编译器会自动优化为单周期加载指令:
#include <stdint.h> typedef int16_t Word16; typedef int32_t Word32; Word32 mac_scalar_4x(const Word16 *pointer1, const Word16 *pointer2) { Word32 sum = 0; // 循环长度64,按4展开共16次迭代 for (int i = 0; i < 64; i += 4) { // 单次加载4个连续Word16到64位寄存器 uint64_t vec1 = *(const uint64_t *)(pointer1 + i); uint64_t vec2 = *(const uint64_t *)(pointer2 + i); // 拆分后做乘累加 sum += ((int16_t)(vec1 & 0xFFFF)) * ((int16_t)(vec2 & 0xFFFF)); sum += ((int16_t)((vec1 >> 16) & 0xFFFF)) * ((int16_t)((vec2 >> 16) & 0xFFFF)); sum += ((int16_t)((vec1 >> 32) & 0xFFFF)) * ((int16_t)((vec2 >> 32) & 0xFFFF)); sum += ((int16_t)((vec1 >> 48) & 0xFFFF)) * ((int16_t)((vec2 >> 48) & 0xFFFF)); } return sum; }
注意:pointer1、pointer2需要按8字节对齐,可通过__attribute__((aligned(8)))修饰指针定义。
2. HVX矢量intrinsics实现(性能更高,推荐用于量产代码)
利用Hexagon HVX矢量单元的并行计算能力,单周期可完成最多8个16位MAC操作,如果要严格按4倍展开可调整步长为4并使用64位矢量加载:
#include <hexagon_types.h> #include <hvx_hexagon_protos.h> typedef int16_t Word16; typedef int32_t Word32; Word32 mac_hvx_4x(const Word16 *pointer1, const Word16 *pointer2) { HVX_Vector sum_vec = Q6_V_vzero(); for (int i = 0; i < 64; i += 4) { // 加载4个16位数据到64位矢量段 HVX_Vector a = Q6_V_vlduh((const HVX_Vector *)(pointer1 + i)); HVX_Vector b = Q6_V_vlduh((const HVX_Vector *)(pointer2 + i)); // 矢量乘累加 sum_vec = Q6_Vw_vaddw_VwVw(sum_vec, Q6_Vw_vmpy_VhVh_s1(a, b)); } // 矢量求和转为标量结果 return Q6_R_sumw_Vw(sum_vec); }
编译时需要添加对应HVX版本参数,比如针对Hexagon v66则添加-mv66 -mhvx=v66,同时开启O2以上优化等级。
3. 汇编实现(性能最优,可完全控制指令调度)
4倍宽度内存加载使用memd指令读取64位数据到d寄存器,示例核心循环如下:
// 输入:r0 = pointer1, r1 = pointer2,输出r0 = sum mac_asm_4x: { r2 = #0 loop0(.mac_loop, #16) // 64/4=16次循环 } .mac_loop: { d0 = memd(r0++#8) // 加载4个16位到d0,指针偏移8字节 d1 = memd(r1++#8) // 加载4个16位到d1,指针偏移8字节 } { r3 = mpy16(d0.l, d1.l) r4 = mpy16(d0.h, d1.h) r2 = add(r2, r3) r2 = add(r2, r4) } { r0 = r2 jumpr r31 }
注意事项
- 所有批量加载操作都要求源指针对齐,64位加载要求8字节对齐,128位HVX加载要求16字节对齐,未对齐会导致性能下降甚至异常
- 如果循环长度可变但始终为4的倍数,将代码中的固定64替换为传入的长度参数即可
内容的提问来源于stack exchange,提问作者lina_2299
相关产品推荐
相关产品推荐

