SIMD指令集

概述

       SIMD,即Single Instruction, Multiple Data,一條指令操作多個數據。是CPU基本指令集的擴展。主要用於提供fine grain parallelism,即小碎數據的並行操作。如說圖像處理,圖像的數據常用的數據類型是RGB565, RGBA8888, YUV422等格式,這些格式的數據特點是一個像素點的一個分量總是用小於等於8bit的數據表示的。如果使用傳統的處理器做計算,雖然處理器的寄存器是32位或是64位的,處理這些數據確只能用於他們的低8位,似乎有點浪費。如果把64位寄存器拆成8個8位寄存器就能同時完成8個操作,計算效率提升了8倍.SIMD指令的初衷就是這樣的,只不過後來慢慢cover的功能越來越多.

       好多處理器都有SIMD指令,我們先僅關注Intel的SIMD。Intel的初代SIMD指令集是MMX,Multi-Media Extension, 即多媒體擴展,因爲它的首要目標是爲了支持MPEG視頻解碼.MMX將64位寄存當作2X32或8X8來用,只能處理整形計算.這樣的64位寄存器有8組,分別命名爲MM0~MM7.這些寄存器不是爲MMX單獨設置的,而是借用的FPU的寄存器,也就是說MMX指令執行的時候,FPU就沒有辦法工作。後來Intel進一步實現了SSE, SSE2~SSE4指令集,給了他們單獨的寄存器,之後MMX就被停掉了。

 

發展歷史

       SSE, SSE2一直到SSE4,AVX都是一代一代發展過來的,基本上是在原來的基礎上增加一些功能,這個增加的過程在網上找到了一張圖可以很好的解釋。

圖中可以看出,SSE首先就是有了屬於自己的8個128位長的寄存器,即32x4,可以支持4個單精度浮點數同時計算,這8個寄存器稱爲XMM0~XMM7, SSE指令要求數據是16byte對齊的.SSE2則進一步支持雙精度浮點數,由於寄存器長度沒有變長,所以只能支持2個雙精度浮點計算或是4個單精度浮點計算.另外,它在這組寄存器上實現了整型計算,從而代替了MMX.SSE3支持一些更加複雜的算術計算.SSE4增加了更多指令,並且在數據搬移上下了一番工夫,支持不對齊的數據搬移,增加了super shuffle引擎.

AVX指令

AVX指令集是Sandy Bridge和Larrabee架構下的新指令集。AVX是在之前的128bit擴展到和256bit的SIMD(Single Instruction, Multiple Data)。而Sandy Bridge的SIMD演算單元擴展到256bits的同時數據傳輸也獲得了提升,所以從理論上看CPU內核浮點運算性能提升到了2倍。
Intel AVX指令集,在SIMD計算性能增強的同時也沿用了的MMX/SSE指令集。不過和MMX/SSE的不同點在於增強的AVX指令,從指令的格式上就發生了很大的變化。x86(IA-32/Intel 64)架構的基礎上增加了prefix(Prefix),所以實現了新的命令,也使更加複雜的指令得以實現,從而提升了x86 CPU的性能。

以上來自百度百科。

       說起AVX來,還有一個有意思的故事。SSE及其後面的進化過程中一直是增加其後面的數字,即SSE2, SSE3, SSE4,按理說下一次進化應該稱爲SSE5。實際上SSE5是存在的,只不過僅存在於AMD的處理器裏。前幾代SSE處理器都是Intel先出,然後AMD跟隨,然而到SSE4之後,突然AMD先出了SSE5,搶了Intel的先。Intel不能忍,於是SSE5就沒了。

2007年8月,AMD搶先宣佈了SSE5指令集(之前從SSE到SSE4均爲Intel制定),當時表示該指令集將於2009年推出的Bulldozer處理器中採用。但Intel隨即表示,不會支持SSE5。轉而在2008年3月,Intel宣佈了Sandy Bridge微架構(Intel Tick-Tock策略:45nm Nehalem - 32nm Westmere - 32nm Sandy Bridge),其中將引入全新的AVX指令集。4月份,Intel公佈了AVX指令集規範,隨後開始不斷進行更新。

以上來自再見SSE5 AMD宣佈支持Intel AVX指令集-AMD,Intel,AVX-驅動之家

根據Dave Christie的說法,AMD在2007年宣佈的SSE5指令集主要包括以下幾項革新:3操作數指令甚至4操作數指令,置換與條件移動指令,乘加指令以及其他一系列解決現有SSE指令集缺陷的新指令。
而Intel在2008年4月公佈的AVX指令集中,同樣包含了SSE5指令集的多項新特性,包括3操作數指令/4操作數指令支持,乘加指令以及部分置換指令等,但實現形式與SSE5不同。並且,AVX指令集還加入了一些SSE5中沒有的新特性:SIMD浮點指令長度加倍,爲舊版SSE指令增加3操作數指令支持,爲未來的指令擴展預留大量OpCode空間等。
由於SSE5和AVX指令集功能類似,並且AVX包含更多的優秀特性,因此AMD決定支持AVX指令集,避免讓軟件開發者因爲要面對兩套不同指令集而徒增開發難度。
不過,由於AVX指令集的制定權在Intel手中,未來還可能進行修改。AMD只能保證,其首款支持AVX指令集產品支持目前的最新版本:2009年1月發佈的AVX第五版規範。並且,FMA乘加指令只支持到2008年8月的AVX第三版規範。

查看系統支持能力

       由於SIMD指令有多個版本,每個版本支持的指令集不同。所以如果你的軟件要支持更多的CPU,就要在使用SIMD指令之前知道當前指令運行所在的CPU是否支持這條指令。

x86/x86_64 提供了CPUID指令,可以通過這個指令查詢當前CPU指令支持SSE指令集情況。CPUID指令可以用來查詢CPU的好多東西,Intel有一個超過100頁的文檔,專門介紹cpuid這條指令。這裏我們僅介紹一下SSE相關的內容,後面如有機會也可以專門介紹一下這條指令。

       首先, CPUID指令是從80486開始纔有,之前的CPU沒有這條指令,當然這個問題大家大可不必擔心,因爲你能用到486之前的處理器的機會機乎沒有,除非你用模擬器去專門模擬這個處理器。在EFLAGS中的bit 21可以識別CPU是否支持CPUID指令,如下圖:

圖片來自圖片上的水印,呵呵

CPUID指令的使用有點類似於一個函數調用,你傳一個參數給CPUID,然後CPUID指令執行後將一些返回值返回給你。你通過EAX寄存器傳參數給CPUID指令,CPUID指令執行完後通過EAX, EBX, ECX, EDX返回給你想的數據。

當輸入EAX==0x1時,EDX返回的擴展信息解釋如下:

位 標號 解釋
0 FPU Floating Point Unit On-Chip. CPU是否內置浮點計算單元
1 VME Virtual 8086 Mode Enhancements. 是否支持虛擬8086模式
2 DE Debugging Extensions. 是否支持調試功能.
3 PSE Page Size Extension. 是否支持大於4MB的分頁.
4 TSC Time Stamp Counter. 是否支持RDTSC指令.(注:RDTSC指令可以計算出CPU的頻率)
5 MSR Module Specific Registers RDMSR and WRMSR Instructions. 是否支持RDMSR與WRMSR (*注1)
6 PAE Physical Address Extension. 是否支持大於32bit的物理地址.
7 MCE Machine Check Exception. (*注2)
8 CX8 CMPXCHG8B Instruction. 是否支持8bytes(64bit)數的比較與交換指令.
9 APIC APIC On-Chip.是否支持APIC(Advanced Programmable Interrupt Controller)
10 保留
11 SEP SYSENTER and SYSEXIT Instructions.是否支持SYSENTER與SYSEXIT指令.(*注3)
12 MTRR Memory Type Range Registers. 是否支持MTTR(*注4)
13 PGE PTE Global Bit. 是否支持全局頁面目錄入口標誌位 (global bit in page directory entries)
14 MCA Machine Check Architecture. 是否支持MCA,MCA是Pentium4,Xeon,P6級處理器的一個錯誤報告機制
15 CMOV Conditional Move Instructions. CMOV指令是否可用.
16 PAT Page Attribute Table. 是否支持PAT,PAT允許操作系統指定4K大小的線性內存空間
17 PSE-36 32-bit Page Size Extension. 是否支持4GB的擴展內存
18 PSN Processor Serial Number. 是否支持處理器序列號.(P3有效)
19 CLFSH CLFLUSH Instruction.是否支持CLFLUSH.(*注5)
20 保留
21 DS Debug Store. 是否支持把調試信息寫入緩存,
22 ACPI ACPI Processor Performance Modulation Registers. 處理器使用特別的寄存器以允許軟件控制處理器的運行週期.
23 MMX Inter MMX Technology.是否支持MMX
24 FXSR FXSAVE and FXRSTOR Instructions. FXSAVE與FXRSTOR指令是否可用(*注6)
25 SSE SSE.是否支持SSE.
26 SSE2 是否支持SSE2.
27 SS Self Snoop. 處理器是否支持總線監視,以防止儲存器衝突.
28 保留
29 TM Thermal Monitor.CPU是否支持溫度控制.

30 & 31 保留

ECX定義如下(資料來自Intel):

bit Name Description
---------------------------------------------------------
00 SSE3 Streaming SIMD Extensions 3
01 Reserved
02 DTES64 64-Bit Debug Store
03 MONITOR MONITOR/MWAIT
04 DS-CPL CPL Qualified Debug Store
05 VMX Virtual Machine Extensions
06 SMX Safer Mode Extensions
07 EST Enhanced Intel SpeedStep® Technology
08 TM2 Thermal Monitor 2
09 SSSE3 Supplemental Streaming SIMD Extensions 3
10 CNXT-ID L1 Context ID
12:11 Reserved
13 CX16 CMPXCHG16B
14 xTPR xTPR Update Control
15 PDCM Perfmon and Debug Capability
17:16 Reserved
18 DCA Direct Cache Access
19 SSE4.1 Streaming SIMD Extensions 4.1
20 SSE4.2 Streaming SIMD Extensions 4.2
21 x2APIC Extended xAPIC Support
22 MOVBE MOVBE Instruction
23 POPCNT POPCNT Instruction
25:24 Reserved
26 XSAVE XSAVE/XSTOR States
27 OSXSAVE
28 AVX
31:29 Reserved

以上可能好多位的含義大家見都沒見過,但只關注SSE~AVX的使能標誌就可以了,後面有機會的話,大家會一一瞭解。

指令示例

乘累加

一個MMX指令來實現乘累加操作是這樣嬸兒的:

這是一個PMADD指令,後綴WD是word的意思,即操作數長度爲word,即16位,在這個示例中,指令完成了兩個乘累加操作,結果爲兩個32位數,放在一個64位寄存器裏.示例是城的a0, a1, a2,a3都是16位數.

這個操作的用處可多了,什麼FFT啊,DCT呀都用得着.

 

SSE指令Single-Scalar和Packed-Scalar

SSE指令的控制更加精細,比如說Single Scalar和Packed Scalar的區別.Single Scalar(-ss後綴)乘法中,四組操作數中有一組操作數進行了計算,其他操作數不動.Packed-Scalar(-ps後綴)乘法中,四組操作數都參與計算.

 

SSE指令Shuffle

shuffle就是對數據重排,比如說常用的shufps,它將四個字段都複製一份同樣的值.

SIMD指令怎麼用?

使用SIMD指令有三種方法,(1)最簡單的方法就是我們寫C/C++代碼,讓編譯器自己轉化。寫代碼的時候遵守某些規則可以幫助編譯器儘量吧。(2)使用編譯器提供的intrinsic,即編譯器實現了一些內置函數和類型,使用它們的時候,對應的操作會翻譯成SIMD指令。(3)寫彙編代碼或是C語言嵌入彙編代碼。

具體用法網上一搜一大堆,就不抄了。

發佈了61 篇原創文章 · 獲贊 61 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章