我试图实现一个需要计算某些数组的dotproduct的应用程序。这需要非常快,所以我考虑用Neon测试SIMD。 我能够重写我的功能以使用SIMD,但是测量的时间与以前几乎相同,有时甚至更多。 没有SIMD,如31秒,SIMD为32秒。
这是我的SIMD代码:
float output = 0.0;
for (int i=0; i<NUMBER_OF_INPUTS; i+=4)
{
in1_126 = vld1q_f32(&source[i]);
in2_126 = vld1q_f32(&weights[i]);
out_126 = vmulq_f32(in1_126, in2_126);
output += vaddvq_f32(out_126);
}
return output;
并且没有:
float output = 0.0;
float tmp;
for(unsigned int i = 0; i < NUMBER_OF_INPUTS; i++)
{
tmp = source[i] * weights[i];
output += tmp;
}
return output;
我已经设置了那些编译器标志:
-mcpu=cortex-a53 -march=armv8-a+simd+crypto
但它没有改变任何东西。
为什么时间几乎没有差异?或者以错误的方式使用NEON让我的dotproduct更快?你有什么其他想法可以让它更快吗?
感谢您的回复!
答案 0 :(得分:3)
你不应该在循环中从向量寄存器移动到标量。
它会导致管道冲洗,每次发生时大约需要14个周期。 (在ARMv7-A
)
这些周期取决于具体的架构。
你可以尝试:
out126 = vmovq_n_f32(0.0f);
for (int i=0; i<NUMBER_OF_INPUTS; i+=4)
{
in1_126 = vld1q_f32(&source[i]);
in2_126 = vld1q_f32(&weights[i]);
out_126 = vmlaq_f32(out_126, in1_126, in2_126);
}
output = vaddvq_f32(out_126);