为什么ARM NEON本质在简单的矢量乘法任务上比C++慢

  • 本文关键字:任务 C++ ARM NEON 简单 c++ neon
  • 更新时间 :
  • 英文 :


我尝试将数据乘以两个浮点指针,并将结果存储到第三个指针中,这是C++代码:

void cpp_version (float *a, float *b, float *c, int counter, int dim) {
for (int i=0; i<counter; ++i) {
for (int j=0; j<dim; ++j) {
c[j] = a[j] * b[j];
}
}
}

通过NEON Intrnsics:进行优化

void neon_version (float *a, float *b, float *c, int counter, int dim) {
for (int i=0; i<counter; ++i) {
for (int j=0; j<dim; j+=4) {
float32x4_t _a = vld1q_f32(a+j), _b = vld1q_f32(b+j);
vst1q_f32(c+j, vmulq_f32(_a, _b));
}
}
}

使用NDK Cmake:交叉编译Android部署(Armv8-a)

cmake -DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake 
-DANDROID_ABI="arm64-v8a" 
-DANDROID_NDK=$NDK 
-DANDROID_PLATFORM=android-22 
..
make

结果是:

average time of neon: 0.0098 ms
average time of c++: 0.0067 ms

为什么NEON比普通C++慢得多?

查看gcc和clang输出:https://godbolt.org/z/5csTEjf5o

Gcc似乎做了一个简单的fmul循环,即使添加了__restrict__,也无法将其矢量化。

Clang展开循环并将其矢量化为8个浮点块:

fmul    v0.4s, v0.4s, v2.4s
fmul    v1.4s, v1.4s, v3.4s

缺少适合你霓虹灯代码的typedef,我看不出它会变成什么。但你一次只能做4次漂浮。一次做8个可能会更快。

您应该为您的浮点向量定义一个正确对齐的结构。理想情况下使用编译时大小。如果编译器知道它是16个与SIMD寄存器对齐的浮点,那么它可以更好地优化这一点。

相关内容

  • 没有找到相关文章