gpt4 book ai didi

c++ - 点积/w Neon Intrinsics

转载 作者:行者123 更新时间:2023-11-30 01:25:56 26 4
gpt4 key购买 nike

我正在尝试使用 Neon 内在函数为 ARM A8 处理器编写优化的点积,但我遇到了一点麻烦。首先,是否有任何库已经实现了这个?我的代码似乎可以工作,但在运行时会导致一些安静的故障——我最好的猜测是因为与未优化的代码相比,精度略有下降。有没有更好的方法来完成我想做的事情?如果有任何帮助或建议,我将不胜感激。提前致谢。

这个特殊的点积是一个 32 位 float * 32 位 float 复数。

这是未优化的代码:

    double sum_re = 0.0;
double sum_im = 0.0;
for(int i=0; i<len; i++, src1++, src2++)
{
sum_re += *src1 * src2->re;
sum_im += *src1 * src2->im;
}

这是我的优化版本:

    float sum_re = 0.0;
float sum_im = 0.0;

float to_sum_re[4] = {0,0,0,0};
float to_sum_im[4] = {0,0,0,0};

float32x4_t tmp_sum_re, tmp_sum_im, source1;
float32x4x2_t source2;
tmp_sum_re = vld1q_f32(to_sum_re);
tmp_sum_im = vld1q_f32(to_sum_im);

int i = 0;

while (i < (len & ~3)) {
source1 = vld1q_f32(&src1[i]);
source2 = vld2q_f32((const float32_t*)&src2[i]);

tmp_sum_re = vmlaq_f32(tmp_sum_re, source1, source2.val[0]);
tmp_sum_im = vmlaq_f32(tmp_sum_im, source1, source2.val[1]);

i += 4;
}
if (len & ~3) {
vst1q_f32(to_sum_re, tmp_sum_re);
vst1q_f32(to_sum_im, tmp_sum_im);

sum_re += to_sum_re[0] + to_sum_re[1] + to_sum_re[2] + to_sum_re[3];
sum_im += to_sum_im[0] + to_sum_im[1] + to_sum_im[2] + to_sum_im[3];
}

while (i < len)
{
sum_re += src1[i] * src2[i].re;
sum_im += src1[i] * src2[i].im;
i++;
}

最佳答案

如果您使用的是 iOS,请使用 Accelerate 框架中的 vDSP_zrdotpr。 (vDSP_zrdotpr 返回实数 vector 与复数 vector 的点积。还有其他变体,例如实数到实数或复数到复数。)

当然会有精度损失;您未优化的代码累积 double 和,而 NEON 代码累积单精度和。

即使不更改精度,结果也会有所不同,因为以不同的顺序执行浮点运算会产生不同的舍入误差。 (对于整数也是如此;如果你计算 7/3*5,你得到 10,但 5*7/3 是 11。)

有一些算法可以减少错误地进行浮点运算。但是,要进行高性能点积,您通常会受困于所得到的。

一种选择是使用 double NEON 指令进行算术运算。当然,这不会像单精度 NEON 那样快,但会比标量(非 NEON)代码快。

关于c++ - 点积/w Neon Intrinsics,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11436551/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com