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 也採用這些額外的暫存器於它的 x86-64(Intel 64)架構。
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。不過 XMM 的暫存器是 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 指令集的處理器 [编辑]
- 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 架構的處理器,包括 Core Duo、Core Solo 等
- Intel Core 2 架構的處理器,包含 Core 2 Duo、Core 2 Quad、Core 2 Extreme 等
- Intel Core i3、Core i5、Core i7 等
- Intel Atom
- Transmeta(全美達)Efficeon
- VIA(威盛)C7
- VIA Nano
不支援 SSE2 處理器的共同特點 [编辑]
SSE2 是 IA-32 架構的延伸。所以目前所有不支援 IA-32 架構的其他架構一概不支援 SSE2。由於 x86-64 架構的處理器是由 IA-32 延伸出來的,所有 x86-64 架構的處理器也都支援 SSE2 指令集。而有些 CPU 並沒有支援 SSE2,但是有其他的指令集可以提供與 SSE2 相似的功能。
下列的 IA-32 架構的處理器是在 SSE2 發表之後才開發的,但是並不支援 SSE2 指令集:
- 比 Athlon 64 早推出的 AMD 處理器,包含了所有使用 Socket A 插槽的處理器。
- 比 Pentium 4 早推出的 Intel 處理器
- VIA 的 C3 處理器
- Transmeta Crusoe 處理器