SSE2

✍ dations ◷ 2024-12-23 11:08:56 #X86架构

SSE2,全名为Streaming SIMD Extensions 2,是一种IA-32架构的SIMD(单一指令多重数据)指令集。SSE2是在 2001年随着Intel发表第一代Pentium 4处理器也一并推出的指令集。它延伸较早的SSE指令集,而且可以完全取代MMX指令集。在2004年,Intel 再度扩展了SSE2指令为 SSE3 指令集。与 70 条指令的 SSE 相比,SSE2新增了144条指令。在2003年,AMD也在发布AMD64的64位处理器时跟进SSE2指令集。

SSE2延伸了MMX指令群使用XMM寄存器来运算,这能让开发人员完全避免让8个64位MMX寄存器与原有的IA-32浮点运算寄存器共享。而这样子就能够不需要切换MMX与x87浮点运算的前提之下混合SIMD标量与浮点向量运算。不过,这不会因为 SSE 的寄存器的精度提高而让运算结果的精度也提高。

而还有部分的SSE2指令集包含了一系列的CPU缓存控制指令。当处理理论上无限的数据流,还有数字格式转换指令所产生出来的大量补码,能够使缓存污染有效的降低。

AMD在AMD64架构上的SSE2再新增额外8个寄存器,把寄存器的量提升到16个(XMM0~XMM15)。这些额外的寄存器只有运行于64位的模式下才能够使用。2004年,Intel也采用这些额外的寄存器于它的86-64(Intel64)架构。

FPU的指令集(x87)通常在运算时使用80位的精度。原始的FPU软件的算法如果套用到SSE2,在数学运算上或是数据输入肯定会造成一些可测得的数值误差。这在科学运算上是很严重的问题,会导致在不同的架构上运算出互不相同的结果。而这问题很容易发生在编译器在解释一条包含好几项运算符(加减乘除)的数学式上。取决于使用哪种编译方式(与最优化),计算过程中会产生不一样的中间值。而在FPU中这些中间值会从80位截成64位。而当这被截掉的中间值拿来运算,最后的数值有可能会大不相同。下面使用G95编译的Fortran代码就是其中一个例子。

program hireal a,b,c,dreal x,y,za=.013b=.027c=.0937d=.79y=-a/b + (a/b+c)*EXP(d)print *,yz=(-a)/b + (a/b+c)*EXP(d)print *,zx=y-zprint *,xend

编译成387浮点运算指令并且运行结果:

# g95 -o hi -mfpmath=387 -fzero -ftrace=full -fsloppy-char hi.for# ./hi0.785871450.78587145.9604645E-8

编译成SSE2指令并且运行结果:

# g95 -o hi -mfpmath=sse -msse2 -fzero -ftrace=full -fsloppy-char hi.for# ./hi0.785871450.785871450.

MMX与SSE2的差别

SSE2让MMX指令群使用XMM寄存器来运算。换句话说,现有的MMX脚本能够完全转换成SSE2。不过SSE2的寄存器是MMX寄存器的两倍大,循环计数器与存储器访问机制也会跟着修改来因应此变化。

而即使一个SSE2指令能够比MMX指令操作多两倍数据量,性能也并没有很明显的提升。有两个主要原因导致此现象:存储器内部访问SSE2的数据并没有以16位组的间隔对齐,这会造成明显的性能损失。还有在大多数的x86架构实现上SSE2的指令吞吐量是小于MMX的。Intel首先面对第一个问题的解决方案是在SSE3指令中新增一个指令,能够在处理未对齐的数据时减少overhead。而第二个问题也在Core 微架构中将运行引擎加宽而解决。

于2000年刚发布的时候,完全没有任何软件开发工具支持SSE2。例如,如果想要在Microsoft Developer Studio里面使用SSE2指令集,程序开发人员就要自己写 inline-assembly,或是从外部来源引入(import)目标代码。后来发布了Visual C++ Processor Pack,才使Visual C++与MASM支持SSE2。

目前Intel官方版的Intel C++编译器能够在不用自行输入assembly而自动编译出SSE4/SSSE3/SSE3/SSE2/SSE的机器代码,能够使程序开发人员专注于更高层的算法开发,而不是汇编阶段的指令集实现。自从Intel发表了 Intel C++ 编译器,它大量增加SSE2于Windows应用程序开发。

自从GCC 3推出,它能够自动生成SSE/SSE2标量码。而SSE/SSE2的自动向量化也新增在GCC 4。

Sun Studio Compiler Suite在使用此-xvector=simd参数时也能够产生SSE2脚本。

SSE2是IA-32架构的延伸。所以目前所有不支持IA-32架构的其他架构一概不支持SSE2。由于x86-64架构的处理器是由IA-32延伸出来的,所有 x86-64架构的处理器也都支持SSE2指令集。而有些CPU并没有支持 SSE2,但是有其他的指令集可以提供与SSE2相似的功能。

下列的IA-32架构的处理器是在SSE2发表之后才开发的,但是并不支持SSE2指令集:

相关