ARM 性能优化实战(四):SIMD 与 NEON 向量化

数据级并行是 ARM 性能的重要来源。这一篇聚焦「SIMD / NEON 向量化」维度,用 NEON 内建函数把一个标量循环向量化,并和编译器自动向量化做个对照。

说明:代码为节选,聚焦「优化前 vs 优化后」的关键差异;完整可编译运行的用例见 arm-perf/cases/ 目录。

01 · ARM NEON SIMD 向量化

把 uint32 数组逐元素相加的标量循环向量化。

❌ 原始代码(性能问题所在)

    /* baseline:标量逐元素相加 */
    uint64_t t0 = now_ns();
    for (uint32_t i = 0; i < N; i++) c[i] = a[i] + b[i];
    uint64_t t1 = now_ns();
    sink_u32(c[N - 1]);
    uint64_t base = t1 - t0;

🔍 慢在哪

标量循环一次只算一个元素,没有利用 CPU 的数据级并行能力。

✅ 优化后的代码

    /* optimized:NEON 一次处理 4 个元素 */
    t0 = now_ns();
    uint32_t i = 0;
    for (; i + 3 < N; i += 4) {
        uint32x4_t va = vld1q_u32(&a[i]);
        uint32x4_t vb = vld1q_u32(&b[i]);
        uint32x4_t vc = vaddq_u32(va, vb);
        vst1q_u32(&c[i], vc);
    }
    for (; i < N; i++) c[i] = a[i] + b[i];
    t1 = now_ns();
    sink_u32(c[N - 1]);
    uint64_t opt = t1 - t0;

    print_result("neon_simd", base, opt);
    return 0;
}
#else
#include <stdio.h>
int main(void) {
    printf("SKIP neon_simd (requires aarch64)n");
    return 0;
}
#endif

🛠 怎么优化

用 NEON 的 128-bit 向量指令(vld1q/vaddq/vst1q)一次加载、运算、写回 4 个 uint32。

📊 实测结果

ARM(aarch64, QEMU):基线 4,248,552 ns → 优化 2,887,390 ns,加速 1.471×。

📱 ARM 视角

NEON 是 ARM 的 SIMD 扩展,图像/音频/加解密等批量运算的提速利器;编译器自动向量化搞不定时,就上手写 intrinsics。


本系列其余文章见「性能优化」分类,或回到《传统ARM优化的思考》看总述。

Leave a Comment

您的邮箱地址不会被公开。 必填项已用 * 标注

Scroll to Top