simd学习
如何查看cpu是否支持simd?
# 检查特定指令集 grep -o avx2 /proc/cpuinfo | head -1 # 检查AVX2 grep -o sse4 /proc/cpuinfo | head -1 # 检查SSE4 grep -o avx512 /proc/cpuinfo | head -1 # 检查AVX512
gcc编译选项,增加支持simd
-mavx2 -D__AVX2__
SSE和AVX2对比
SSE(Streaming SIMD Extensions)
基本特性:
引入时间:1999年(Pentium III)
寄存器宽度:128位(16字节)
寄存器数量:8个(XMM0-XMM7)
数据并行度:一次处理多个数据元素
数据类型:
cpp
__m128i // 处理整数(16个char,8个short,4个int,2个long) __m128 // 处理单精度浮点数(4个float) __m128d // 处理双精度浮点数(2个double)
常见操作:
cpp
// 加载和存储 __m128i data = _mm_loadu_si128(ptr); // 加载16字节 _mm_storeu_si128(ptr, data); // 存储16字节// 算术运算 __m128i sum = _mm_add_epi32(a, b); // 4个int同时相加 __m128i prod = _mm_mullo_epi16(a, b); // 8个short同时相乘
AVX2(Advanced Vector Extensions 2)
基本特性:
引入时间:2013年(Haswell架构)
寄存器宽度:256位(32字节)← 比SSE翻倍
寄存器数量:16个(YMM0-YMM15)← 比SSE翻倍
向后兼容:包含所有SSE功能
数据类型:
cpp
__m256i // 处理整数(32个char,16个short,8个int,4个long) __m256 // 处理单精度浮点数(8个float) __m256d // 处理双精度浮点数(4个double)
增强功能:
cpp
// 更丰富的指令集 __m256i data = _mm256_loadu_si256(ptr); // 加载32字节 _mm256_storeu_si256(ptr, data); // 存储32字节// 新的操作类型 __m256i gather = _mm256_i32gather_epi32(base, index, scale); // 聚集加载
4. 直观对比
处理32个字符(char):
技术 | 指令数 | 寄存器使用 | 性能 |
---|---|---|---|
逐字节 | 32条加载 + 32条存储 | 1个通用寄存器 | 1x |
SSE | 2条加载 + 2条存储 | 2个XMM寄存器 | 16x |
AVX2 | 1条加载 + 1条存储 | 1个YMM寄存器 | 32x |
SSE和AVX2的关系就像:
SSE = 小货车(一次运16箱货物)
AVX2 = 大卡车(一次运32箱货物)
两者都是SIMD技术,但:
AVX2更强大(寄存器更大,指令更多)
SSE更兼容(支持更广泛的硬件)
AVX2包含SSE(向后兼容)
在高性能编程中,我们通常:
优先使用AVX2(如果可用)
降级使用SSE(作为备选)
提供回退方案(保证兼容性)