为何现代编译器不对简单代码自动生成SSE/AVX向量化指令?
x86-64架构下SSE/AVX向量化的编译器行为疑惑
近期我深入研究x86-64架构,探索SSE(1999年推出)与AVX(2011年推出)指令集的能力。我编写了如下简单向量加法函数:
void compute(const float *a, const float *b, float *c) { c[0] = a[0] + b[0]; c[1] = a[1] + b[1]; c[2] = a[2] + b[2]; c[3] = a[3] + b[3]; }
使用gcc与clang,通过以下编译选项构建:
cc -std=c23 -march=native -O3 -ftree-vectorize main.c
但查看反汇编结果后,发现代码并未如预期实现向量化,生成的是逐个处理元素的标量代码:
compute: vmovss xmm0, dword ptr [rdi] vaddss xmm0, xmm0, dword ptr [rsi] vmovss dword ptr [rdx], xmm0 vmovss xmm0, dword ptr [rdi + 4] vaddss xmm0, xmm0, dword ptr [rsi + 4] vmovss dword ptr [rdx + 4], xmm0 vmovss xmm0, dword ptr [rdi + 8] vaddss xmm0, xmm0, dword ptr [rsi + 8] vmovss dword ptr [rdx + 8], xmm0 vmovss xmm0, dword ptr [rdi + 12] vaddss xmm0, xmm0, dword ptr [rsi + 12] vmovss dword ptr [rdx + 12], xmm0 ret
不过当手动使用intrinsics编写代码时,得到了预期的向量化实现:
#include <xmmintrin.h> void compute(const float *a, const float *b, float *c) { __m128 va = _mm_loadu_ps(a); __m128 vb = _mm_loadu_ps(b); __m128 vc = _mm_add_ps(va, vb); _mm_storeu_ps(c, vc); }
我知道现代处理器性能强劲,SSE与AVX早已成为主流指令集,但即使显式开启了全优化选项,编译器似乎也不总能充分利用这些指令。为何现代编译器会对如此直白的代码犹豫生成向量化代码?
有人提到4个元素可能不足以体现向量化的性能优势,于是我尝试了处理更大数组的代码,本地编译后仍得到类似的标量结果:
float a[512]; float b[512]; float c[512]; void compute() { for (size_t i = 0; i < 512; i++) c[i] = a[i] + b[i]; }
(注:在本地编译未触发向量化,但在Godbolt上,GCC使用-O3 -march=x86-64-v3选项会自动生成256位AVX指令实现向量化。)
内容的提问来源于stack exchange,提问作者nowox
相关产品推荐
相关产品推荐

