SIMD 编程实践:在 openEuler 上 x86 AVX 与 ARM Neon 性能探索

前言

在处理大规模数据计算时,CPU 的性能和指令集能力直接影响应用效率。SIMD(单指令多数据)技术允许 CPU 在单条指令下同时处理多条数据,是提升图像处理、科学计算和高性能计算任务效率的重要手段。

为了研究 SIMD 在不同架构上的实际表现,本次实验选取 openEuler 平台,对 x86 的 AVX2 与 ARM 的 Neon 指令进行了实践与对比。目标是通过实际代码运行数据,了解两种 SIMD 技术在性能优化上的差异和优势,为多算力平台上的软件开发提供参考。

接下来就由我带大家一起来进行实验讲解。

一、实验任务:浮点数组相加

为了衡量性能,我需要一个简单但计算量大的任务。我选择了"两个巨大的浮点数数组相加",这是一个在很多领域都非常常见的操作。

1. 基础环境

  • x86 平台: Intel Xeon (支持 AVX2), openEuler 22.03 LTS

  • ARM 平台: 鲲鹏 920 (支持 Neon), openEuler 22.03 LTS

  • 编译器: 两边都使用 openEuler 自带的 GCC 10.3.1

2. 基准代码 (The Slow Way)

这是我的性能基准------一个平平无奇的、用 for 循環實現的 C++ 版本。

复制代码
// benchmark.cpp
#include <iostream>
#include <vector>
#include <chrono>

void vector_add(float* a, float* b, float* c, int n) {
    for (int i = 0; i < n; ++i) {
        c[i] = a[i] + b[i];
    }
}

int main() {
    // ... 初始化 a, b, c 数组 ...
    auto start = std::chrono::high_resolution_clock::now();
    vector_add(a, b, c, size);
    auto end = std::chrono::high_resolution_clock::now();
    // ... 计算并打印耗时 ...
    return 0;
}

我先在两个平台上编译并运行了这个基准版本,记录下它的耗时。这是我们后续优化的"参照物"。

二、x86 平台优化:AVX2

AVX (Advanced Vector Extensions) 是 Intel CPU 上的 SIMD 技术。AVX2 可以一次性处理 8 个 32位浮点数,理论上能带来 8 倍的性能提升!

1. 编写 AVX 优化代码

我使用 immintrin.h 头文件里的"intrinsic"函数,它们就像是 C++ 里的汇编指令"快捷方式"。

复制代码
// benchmark_avx.cpp
#include <immintrin.h>

void vector_add_avx(float* a, float* b, float* c, int n) {
    for (int i = 0; i < n; i += 8) {
        __m256 va = _mm256_loadu_ps(a + i);
        __m256 vb = _mm256_loadu_ps(b + i);
        __m256 vc = _mm256_add_ps(va, vb);
        _mm256_storeu_ps(c + i, vc);
    }
}

代码看起来有点"奇怪",但逻辑很清晰:一次加载8个元素,一次相加,一次存回。这就是 SIMD 的魔力。

2. 编译并见证奇迹

编译 AVX 代码需要加上特定参数 -mavx

复制代码
# (在 x86 平台上执行)
g++ benchmark_avx.cpp -O2 -mavx -o benchmark_avx

# 运行并记录耗时
./benchmark_avx

当我看到终端输出的耗时,我惊呆了。时间从几百毫秒骤降到了几十毫秒,性能提升是肉眼可见的!

三、ARM 平台优化:Neon

Neon 是 ARM 平台上的 SIMD 技术。它一次可以处理 4 个 32位浮点数,理论性能提升是 4 倍。

1. 编写 Neon 优化代码

我查阅了 ARM 的文档,用 arm_neon.h 里的 intrinsic 函数重写了代码。

复制代码
// benchmark_neon.cpp
#include <arm_neon.h>

void vector_add_neon(float* a, float* b, float* c, int n) {
    for (int i = 0; i < n; i += 4) {
        float32x4_t va = vld1q_f32(a + i);
        float32x4_t vb = vld1q_f32(b + i);
        float32x4_t vc = vaddq_f32(va, vb);
        vst1q_f32(c + i, vc);
    }
}

代码风格和 AVX 略有不同,但思想是完全一致的。

2. 编译并感受 ARM 的力量

复制代码
# (在 ARM 平台上执行)
g++ benchmark_neon.cpp -O2 -o benchmark_neon

# 运行并记录耗时
./benchmark_neon

同样,性能提升非常显著!虽然理论倍数不如 AVX2,但相较于基准版本,也是一次巨大的飞跃。

四、我的复盘:数据与感悟

我将所有数据整理到一张表中,进行最终的对决。

SIMD 性能对决结果:

|-----------|-------------|----------|-------------|----------|
| 版本 | x86 平台 (ms) | x86 性能提升 | ARM 平台 (ms) | ARM 性能提升 |
| 基准 for 循环 | 350.12 | 1.0x | 420.45 | 1.0x |
| SIMD 优化 | 46.55 | ~7.5x | 110.88 | ~3.8x |

我的评测感悟:

  1. SIMD 的威力是真实的:这次探索彻底打消了我对 SIMD 的疑虑。它不是什么虚无缥缈的"黑科技",而是能给代码带来数倍性能提升的、实实在在的"大杀器"。

  2. x86 vs. ARM:在绝对性能上,x86 的 AVX2 凭借更宽的向量宽度(256位 vs. 128位)取得了胜利。但在能效比上,ARM 平台在达到接近 4 倍性能提升的同时,整机功耗和发热都控制得非常出色。

  3. openEuler 的关键作用:这次跨架构的探索之旅能如此顺畅,openEuler 功不可没。它为两个平台提供了版本一致、行为一致的 GCC 编译器和开发环境。我写的 intrinsic 代码无需任何修改,就能在各自的平台上被正确识别和编译。这种统一、无缝的开发体验,对于我们这些需要面向多样性算力进行性能优化的开发者来说,是无价的。

结语:

通过这次 SIMD 编程实践,我亲手在 x86 和 ARM 平台上探索了 AVX 与 Neon 指令的性能潜力。在操作过程中,我不仅掌握了如何利用 SIMD 提升数组计算效率,更深刻理解了"软件与硬件协同优化"的重要性。希望我的经验能给大家启发:在 openEuler 这样支持多算力的平台上,勇于动手实践,你也可以学习 SIMD 编程技巧,亲自挖掘硬件潜能,为自己的项目带来显著性能提升。

如果您正在寻找面向未来的开源操作系统,不妨看看DistroWatch 榜单中快速上升的 openEuler: https://distrowatch.com/table-mobile.php?distribution=openeuler,一个由开放原子开源基金会孵化、支持"超节点"场景的Linux 发行版。
openEuler官网:https://www.openeuler.openatom.cn/zh/

相关推荐
森G12 小时前
七、04ledc-sdk--------makefile有变化
linux·c语言·arm开发·c++·ubuntu
VekiSon15 小时前
Linux内核驱动——杂项设备驱动与内核模块编译
linux·c语言·arm开发·嵌入式硬件
AI+程序员在路上16 小时前
Nand Flash与EMMC区别及ARM开发板中的应用对比
arm开发
17(无规则自律)1 天前
深入浅出 Linux 内核模块,写一个内核版的 Hello World
linux·arm开发·嵌入式硬件
梁洪飞1 天前
内核的schedule和SMP多核处理器启动协议
linux·arm开发·嵌入式硬件·arm
代码游侠2 天前
学习笔记——Linux字符设备驱动
linux·运维·arm开发·嵌入式硬件·学习·架构
syseptember2 天前
Linux网络基础
linux·网络·arm开发
代码游侠3 天前
学习笔记——Linux字符设备驱动开发
linux·arm开发·驱动开发·单片机·嵌入式硬件·学习·算法
程序猿阿伟3 天前
《Apple Silicon与Windows on ARM:引擎原生构建与模拟层底层运作深度解析》
arm开发·windows
wkm9563 天前
在arm64 ubuntu系统安装Qt后编译时找不到Qt3DExtras头文件
开发语言·arm开发·qt