arm - 在简单的加法任务中使用 ARM NEON 速度较慢
问题描述
我尝试编写一段简单的 NEON 代码,但发现它比常规的 C++ 实现要慢。代码如下
float A[] = {1,2,3,4};
float B[] = {2,3,4,5};
float32x4_t v1;
float32x4_t v2;
int counter = 1000000;
while(counter--){
v1 = vld1q_f32(A);
v2 = vld1q_f32(B);
v = vaddq_f32(v1,v2);
vst1q_f32(A,v);
// A[0] = A[0]+B[0]; // regular implementation
// A[1] = A[1]+B[1]; // regular implementation
// A[2] = A[2]+B[2]; // regular implementation
// A[3] = A[3]+B[3]; // regular implementation
}
我搜索了原因,所以我猜是因为顺序管道和这个简单的任务导致 CPU 停顿?但是有人能帮忙解释得更详细吗?有什么方法可以提高这个 NEON 实现的性能吗?还是在面对这种简单的任务时使用常规实现比使用 NEON 更好?谢谢你。
解决方案
您的测试程序从一开始就完全有缺陷:
由于编译器在构建时可以清楚地看到所有输入,因此编译器将简单地生成类似于以下的机器代码:
A[0] = 3.0f;
A[1] = 5.0f;
A[2] = 7.0f;
A[3] = 9.0f;
为了防止编译器进行这种作弊,您必须隐藏输入:
void myFunc_c(float *pA, float *pB, uint32_t count)
{
if (count == 0) return;
do {
*pA++ += *pB++;
} while (--count);
}
void myFunc_neon(float *pA, float *pB, uint32_t count)
{
float32x4_t a, b;
count >>= 2;
if (count == 0) return;
do {
a = vld1q_f32(pA);
b = vld1q_f32(pB);
a = vaddq_f32(a, b);
vst1q_f32(pA, a);
pA += 4;
pB += 4;
} while (--count);
}
您需要做的就是为pA
and分配足够的内存pB
,如果需要,初始化它们,然后调用上面的函数。
我认为霓虹灯版本会快大约 3 倍。
推荐阅读
- operating-system - 每个系统调用是否创建一个进程?
- matplotlib - 如何绘制多个相互堆叠的图形
- java - 加载序列化的 Ecore 模型作为 XMI 无法正确加载容器
- c - C中具有不同数据类型的键值
- .net-core - 在本地网络中运行 .net core web api
- python - 检查是否在 Python 中定义了要避免的变量?
- java - ProgressBar 崩溃活动(空对象引用/或不可见)
- html - 在保持切换菜单(汉堡)的同时更改导航栏背景颜色
- node.js - 如何在嵌套中间件中设置 cookie 和使用上下文
- azure - 具有项目依赖项的项目的 Helm 安装失败