SIMD全称是"Single Instruction, Multiple Data".
SSE1是Pentium III引入的,它操作于16 bytes寄存器。在C和C++中,这些寄存器以__m128的形式作为数据类型(128 bits=16 bytes)。每个寄存器包含4个单精度浮点数float,指令集一共有8个这样的寄存器,他们被命名为xmm0到xmm7。
SSE2是2000年Pentium 4引入的,它增加了支持双精度浮点数和整型数的SIMD指令。SSE2还是操作同样的8个寄存器,但是为了类型安全,双精度浮点数和整型数以__m128d和__m128i的形式作为数据类型。
2003年,AMD引入了AMD64架构,增加了8个向量寄存器,新增的8个寄存器被命名为xmm8到xmm15。
2011年,Intel在Sandy Bridge处理器中引入了AVX。AVX将寄存器从16 bytes扩展到32 bytes,所以寄存器就可以包含8个单精度浮点数float或者4个双精度浮点数double。寄存器的个数并没有变化,还是16个。在汇编语言中,寄存器被新命名为ymm0到ymm15,它们的低128位仍然可以以xmm0到xmm15的名字访问。AVX同时支持32位和64位浮点数,但是并不完全支持整型。
2013年,Intel引入了AVX2。AVX2增加了对整型数据运算的支持,但并没有增加新寄存器。AVX和AVX2现在已经广泛支持了。具体硬件支持历史可以看下图:
记住,在编译64位程序时,一共有16个寄存器可供使用,但编译32位程序时,只有8个。编译器总是自动的将变量赋值到寄存器里,但是如果你定义了太多的局部变量,或者代码逻辑牵扯很多变量依赖关系导致编译器无法重复使用寄存器,那么编译器会把变量移到RAM上。而这样在某些情况下,会给程序性能带来负面影响。
_mm256_load_ps和_mm256_loadu_ps的区别:
不带u表示指令要求它所操作的数据内存地址必须是16或32 bytes对齐的(align);
带u表示指令支持操作非内存对齐的地址,但是如果数据内存地址是对齐的,那么操作也会更快。