ARM Neon 内在函数,两个向量相加
ARM Neon intrinsics, addition of two vectors
我有一个非常简单的 C 函数,将两个整数数组成对相加:
void add_arrays(int* a, int* b, int* target, int size) {
for(int i=0; i<size; i++) {
target[i] = a[i] + b[i];
}
}
我看到在 ARM 上, 中提供了 Neon 内在函数,您应该可以对向量进行加法、乘法等操作,但我看到的所有示例都非常复杂。有人可以展示如何使用 ARM Neon 内在函数执行简单的操作,例如成对加法吗?
更新
我的术语是错误的,我希望实现逐元素加法。
首先,正如 Jake 提到的,这段代码所做的是 而不是 成对加法。成对添加将添加相邻的对;像
void add_arrays(int* a, int* target, int size) {
for(int i=0; i<size; i++) {
target[i] = a[i * 2] + a[(i * 2) + 1];
}
}
这可以使用 NEON 来完成,但我假设您的代码是正确的,但对于此答案的其余部分,您的术语是错误的。如果情况相反,这个答案加上查看 vpaddq_s32
(或者 vpaddl_s32
)的文档应该可以帮助您完成大部分工作。
为简单起见,我假设大小是 4 的倍数(因为 4 个 32 位元素 = 1 个 128 位向量),所以:
void add_arrays(int* a, int* b, int* target, int size) {
for(int i=0; i<size; i+=4) {
target[ i ] = a[ i ] + b[ i ];
target[i + 1] = a[i + 1] + b[i + 1];
target[i + 2] = a[i + 2] + b[i + 2];
target[i + 3] = a[i + 3] + b[i + 3];
}
}
现在让我们添加一些 NEON 内在函数:
#include <arm_neon.h>
void add_arrays(int* a, int* b, int* target, int size) {
for(int i=0; i<size; i+=4) {
/* Load data into NEON register */
int32x4_t av = vld1q_s32(&(a[i]));
int32x4_t bv = vld1q_s32(&(b[i]));
/* Perform the addition */
int32x4_t targetv = vaddq_s32(av, bv);
/* Store the result */
vst1q_s32(&(target[i]), targetv);
}
}
就是这样。您可以在 https://godbolt.org/z/W6KPv186x.
处查看生成代码的差异
我有一个非常简单的 C 函数,将两个整数数组成对相加:
void add_arrays(int* a, int* b, int* target, int size) {
for(int i=0; i<size; i++) {
target[i] = a[i] + b[i];
}
}
我看到在 ARM 上,
更新 我的术语是错误的,我希望实现逐元素加法。
首先,正如 Jake 提到的,这段代码所做的是 而不是 成对加法。成对添加将添加相邻的对;像
void add_arrays(int* a, int* target, int size) {
for(int i=0; i<size; i++) {
target[i] = a[i * 2] + a[(i * 2) + 1];
}
}
这可以使用 NEON 来完成,但我假设您的代码是正确的,但对于此答案的其余部分,您的术语是错误的。如果情况相反,这个答案加上查看 vpaddq_s32
(或者 vpaddl_s32
)的文档应该可以帮助您完成大部分工作。
为简单起见,我假设大小是 4 的倍数(因为 4 个 32 位元素 = 1 个 128 位向量),所以:
void add_arrays(int* a, int* b, int* target, int size) {
for(int i=0; i<size; i+=4) {
target[ i ] = a[ i ] + b[ i ];
target[i + 1] = a[i + 1] + b[i + 1];
target[i + 2] = a[i + 2] + b[i + 2];
target[i + 3] = a[i + 3] + b[i + 3];
}
}
现在让我们添加一些 NEON 内在函数:
#include <arm_neon.h>
void add_arrays(int* a, int* b, int* target, int size) {
for(int i=0; i<size; i+=4) {
/* Load data into NEON register */
int32x4_t av = vld1q_s32(&(a[i]));
int32x4_t bv = vld1q_s32(&(b[i]));
/* Perform the addition */
int32x4_t targetv = vaddq_s32(av, bv);
/* Store the result */
vst1q_s32(&(target[i]), targetv);
}
}
就是这样。您可以在 https://godbolt.org/z/W6KPv186x.
处查看生成代码的差异