SSE2
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的更动
[编辑]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)架构。
x87浮点运算器与SSE2的差别
[编辑]FPU的指令集(x87)通常在运算时使用80位元的精度。原始的FPU软体的演算法如果套用到SSE2,在数学运算上或是资料输入肯定会造成一些可测得的数值误差。这在科学运算上是很严重的问题,会导致在不同的架构上运算出互不相同的结果。而这问题很容易发生在编译器在解释一条包含好几项运算子(加减乘除)的数学式上。取决于使用哪种编译方式(与最佳化),计算过程中会产生不一样的中间值。而在FPU中这些中间值会从80位元截成64位。而当这被截掉的中间值拿来运算,最后的数值有可能会大不相同。下面使用G95编译的Fortran程式码就是其中一个例子。
program hi
real a,b,c,d
real x,y,z
a=.013
b=.027
c=.0937
d=.79
y=-a/b + (a/b+c)*EXP(d)
print *,y
z=(-a)/b + (a/b+c)*EXP(d)
print *,z
x=y-z
print *,x
end
编译成387浮点运算指令并且执行结果:
# g95 -o hi -mfpmath=387 -fzero -ftrace=full -fsloppy-char hi.for
# ./hi
0.78587145
0.7858714
5.9604645E-8
编译成SSE2指令并且执行结果:
# g95 -o hi -mfpmath=sse -msse2 -fzero -ftrace=full -fsloppy-char hi.for
# ./hi
0.78587145
0.78587145
0.
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指令码。
Microsoft Visual C++ 2012 开始,在预设的情况下会启用用于生成SSE2指令的编译器选项。
支援SSE2指令集的处理器
[编辑]- Athlon 64、Sempron 64、Turion 64等为主的AMD K8架构处理器
- Phenom、Phenom II、Athlon II等为主的AMD K10、AMD K10.5架构处理器
- Pentium 4、Xeon、Celeron、Celeron D等为主的Intel NetBurst架构的处理器
- Intel Pentium M与Celeron M
- Intel Core 2架构的处理器
- Intel Core i3、Core i5、Core i7等
- Atom
- Transmeta(全美达)Efficeon
- VIA(威盛)C7
- VIANano
不支援SSE2处理器的共同特点
[编辑]SSE2是IA-32架构的延伸。所以目前所有不支援IA-32架构的其他架构一概不支援SSE2。由于x86-64架构的处理器是由IA-32延伸出来的,所有 x86-64架构的处理器也都支援SSE2指令集。而有些CPU并没有支援 SSE2,但是有其他的指令集可以提供与SSE2相似的功能。
下列的IA-32架构的处理器是在SSE2发表之后才开发的,但是并不支援SSE2指令集:
- 比Athlon64早推出的AMD处理器,包含了所有使用 Socket A 插槽的处理器。
- 比Pentium 4早推出的Intel处理器
- VIA的C3 处理器
- 全美达的Crusoe处理器
- Intel Quark