C++ SIMD编程核心是使用Intel intrinsic函数,需关注数据对齐、寄存器宽度与编译器优化;从128位SSE(4×float/2×double)起步,再升级至256位AVX(8×float)及AVX2/AVX-512,注意内存对齐、指令混用和编译选项控制。

用C++做SIMD编程,核心是调用Intel提供的intrinsic函数——它们是编译器内建的、可直接映射到CPU向量指令(如SSE、AVX)的C++函数,比手写汇编友好,又比纯标量代码快得多。关键不是“会不会写”,而是理解数据布局、指令对齐、寄存器宽度和编译器行为。
从SSE开始:128位向量最稳当
SSE(Streaming SIMD Extensions)支持4个float或2个double同时运算,兼容性最好(奔腾4起就支持)。先确保头文件和数据对齐:
-
#include
—— 统一包含所有x86 intrinsic - 输入数组必须16字节对齐(_mm_malloc(16 * n, 16) 或 alignas(16) float a[4])
- 加载:用 _mm_load_ps(ptr)(要求ptr地址%16==0),不满足用 _mm_loadu_ps(慢一点但安全)
- 计算:比如 __m128 a = _mm_load_ps(x); __m128 b = _mm_load_ps(y); __m128 c = _mm_add_ps(a, b);
- 存回:_mm_store_ps(out, c)(对齐)或 _mm_storeu_ps(非对齐)
升级到AVX:256位宽,一算就是8个float
AVX(2011年Core i7起)把向量宽度翻倍,指令名多带一个v(如_mm256_add_ps),需32字节对齐:
- 分配内存:float* p = (float*)_mm_malloc(32 * n, 32);
- 加载8个float:__m256 a = _mm256_load_ps(p);
- 注意:AVX指令会清零高位(YMM寄存器高128位),混用SSE指令前建议加_mm256_zeroupper()防性能损失
- AVX2支持整数运算(如_mm256_add_epi32),AVX-512则支持512位和掩码操作(需新CPU和编译器支持)
别让编译器“帮你优化”掉你的SIMD
写了intrinsics,结果性能没提升?很可能是编译器做了冲突优化或没开对选项:
版权声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。
还木有评论哦,快来抢沙发吧~