SIMD 與 SIMT 的差異:執行模型、程式撰寫、分支、記憶體存取比較

SIMD 與 SIMT 都是以 1 道指令對大量資料進行相同運算,但從程式看到的樣貌不同。SIMD 是 CPU 的向量指令,由程式設計師或編譯器將資料排列在寬度固定的向量暫存器中,並明確地使用指令。SIMT 是 GPU 的方式,只要以一般方式撰寫 1 個執行緒的處理,硬體就會將 32 個等數量的執行緒集結成 warp,以相同指令執行。每個執行緒也可以撰寫分支,但若 warp 內的分支走向不同,就會依序執行兩條路徑,效率因而下降。

項目SIMDSIMT
執行模型以 1 道指令同時處理排列在向量暫存器中的多個元素由集結成 warp 的大量執行緒同時執行 1 道指令。每個執行緒擁有自己的暫存器
從程式看到的樣貌意識著向量寬度撰寫。使用內建函式、組合語言或編譯器的自動向量化將 1 個執行緒的處理寫成純量程式碼。由硬體進行集結
平行寬度由暫存器寬度決定。例:512 位元可容納 16 個 32 位元的數warp 的寬度(32 個執行緒等)。整顆晶片可同時保有數萬個執行緒
分支的處理無法撰寫各元素的分支。以比較結果的遮罩計算兩邊後再選擇可依執行緒撰寫。若 warp 內分歧,會依序執行兩條路徑,讓不符合的執行緒閒置(分支發散)
有效元素的管理由程式設計師或編譯器以帶遮罩的指令或混合指令明確指定由硬體自動管理有效的執行緒
記憶體存取擅長一次讀取連續的位址。分散的位址以收集、分散(gather/scatter)指令處理,但速度慢每個執行緒可以自由指定位址。相鄰執行緒讀取相鄰位址時可合併存取(coalescing)
記憶體延遲的隱藏方式大容量快取、亂序執行、預取切換大量 warp,在某些 warp 等待期間執行其他 warp
在弗林分類法中的定位SIMD 本身以執行緒形式呈現的一種 SIMD
代表性用途CPU 的向量指令。影像與聲音處理、加密、矩陣運算的迴圈等GPU 的 warp。圖形、AI 的訓練與推論、科學計算等大規模平行計算

數值為具代表性的大致參考值,會因世代或產品而異。

適用於什麼情況

SIMD
想在 CPU 上加速對陣列每個元素進行相同計算的迴圈時。資料連續排列且迭代之間沒有相依性時效果大,也可透過編譯器的自動向量化使用。
SIMT
對數千至數百萬個獨立元素進行相同處理的大規模平行計算。在 GPU 上撰寫並執行每個執行緒的程式。將程式設計成 warp 內的分支與記憶體位址一致,效率就會提高。
搭配使用
在 GPU 內部,以 warp 為單位的 SIMT 執行是在 SIMD 運算單元上進行的。在同時使用 CPU 與 GPU 的系統中,前處理與控制由 CPU 的 SIMD 負責,大型平行計算由 GPU 負責。

常見問題

SIMT 與 SIMD 是完全不同的機制嗎?

在硬體內部是相近的機制。warp 的每個執行緒對應 SIMD 運算單元的 1 條通道,以相同指令運作。差別在於呈現方式:SIMT 由硬體處理每個執行緒的暫存器、位址與分支,因此程式設計師不必意識到向量寬度就能撰寫。

如何減少 warp 分支發散?

讓同一個 warp 的執行緒盡量走同一側的分支。例如重新排列資料使條件結果一致、分配執行緒編號使條件以 warp 為單位切換、將短分支替換為選擇運算等方法。

在 SIMD 中,含有 if 敘述的處理要怎麼寫?

以比較指令將每個元素的條件做成遮罩,計算兩邊的結果後,再依遮罩逐元素選擇。在具有帶遮罩指令的指令集中,可以只對符合條件的元素進行運算與儲存。由於兩條路徑都要計算,分支內容較重時效率會下降,這一點與 SIMT 的分支發散相似。

編譯器的自動向量化在什麼情況下會失敗?

迭代之間有相依性時(下一次會用到前一次的結果)、指標可能指向同一區域時、資料沒有連續排列時、迴圈中有複雜的分支或函式呼叫時等。告知編譯器沒有相依性的指定,或改變資料的排列方式,有時就能向量化。

理解度檢測

以一道指令同時對多筆資料進行相同運算的方式是下列何者?

  1. ASISD
  2. BSIMD
  3. CMISD
查看答案與解析

正確答案:B. SIMD

SIMD 是以一道指令對多筆資料平行進行相同運算的方式,例如 512 位元的暫存器可一次計算 16 個 32 位元的數值。有 x86 的 SSE、AVX,ARM 的 NEON、SVE 等,在影像處理、視訊壓縮、矩陣運算等方面可獲得數倍以上的加速。依弗林分類法(Flynn's taxonomy),另外還有 SISD(一般的循序處理)、MIMD(多核心)等。

在NVIDIA的GPU中,將32個執行緒組成一束並同時執行相同指令的單位稱為什麼?

  1. A線程束(warp)
  2. B網格(grid)
  3. C分頁(page)
查看答案與解析

正確答案:A. 線程束(warp)

區塊中的執行緒在硬體內部會以每32個為一組,分成線程束(warp),同一個線程束的32個執行緒會同時對各自不同的資料執行相同的指令。像這樣將以執行緒方式撰寫的程式集結成一束,並以相同指令運作的方式,稱為SIMT。AMD的GPU將類似的單位稱為wavefront,為64個或32個。區塊的大小基本上應設為32的倍數。

關於GPU的SIMT(單一指令、多執行緒)方式與CPU的SIMD指令之差異,下列何者正確?

  1. ASIMT對一筆資料同時執行多個指令,SIMD則對一筆資料執行一個指令
  2. BSIMT與SIMD完全相同,只是名稱不同
  3. CSIMT可將各執行緒寫成獨立的程式,分支也由硬體處理,而SIMD則需由程式設計師或編譯器明確使用寬度固定的向量指令
查看答案與解析

正確答案:C. SIMT可將各執行緒寫成獨立的程式,分支也由硬體處理,而SIMD則需由程式設計師或編譯器明確使用寬度固定的向量指令

CPU的SIMD是對集結了4個或8個資料的向量暫存器施加一個指令,因此撰寫程式時必須留意向量的寬度。GPU的SIMT則是程式設計師照一般方式撰寫一個執行緒的處理,再由硬體每32個一組,以相同指令運作。各執行緒也可以分支,硬體會依序執行分歧出的路徑,但此時效率會下降。

  1. 在一個線程束中,因條件分支使一半的執行緒走if側、另一半走else側(線程束發散,warp divergence)。一般會如何執行?
  2. 關於GPU的記憶體合併存取(coalescing),下列說明何者正確?
  3. 編譯器的自動向量化所使用的指令種類,下列何者正確?

前往GPU程式設計的練習題

相關名詞的解說

SIMD
為 Single Instruction, Multiple Data 的縮寫。以 1 個指令對多筆資料同時進行相同運算的方式。可加速影像處理與 AI 的計算。
SIMT(單指令多執行緒)
單一指令、多個執行緒的方式。程式是以每個執行緒為單位撰寫,但硬體會以 warp(NVIDIA 為 32 個)為單位將執行緒綁在一起,以相同指令執行。
Warp 分歧(Warp divergence)
在同一個 warp 內,因條件分支而使執行緒走的路徑分開的現象。由於會依序執行分開的路徑,效率會下降。
記憶體合併存取(Memory coalescing)
當 warp 內相鄰的執行緒存取相鄰的位址時,將其合併為較少次數的記憶體存取。
向量化
將迴圈中逐元素進行的相同計算,改為使用SIMD指令一次對多個元素進行的最佳化。條件是重複之間沒有資料相依。

相關的比較