高效能與平行計算

GPU 運算(GPU computing)

CPU 像幾位才華洋溢的主廚,每位都能快速照著複雜食譜做。GPU 像一座擠滿備料工的體育場,每個都慢而簡單,但有數千個,全都同時做著完全相同的切菜動作。要做一頓花俏多變的餐你想要主廚;但要以同樣方式削一萬顆馬鈴薯,那支備料工大軍轉眼就完工。GPU 運算就是把數值工作改鑄成第二種形狀的藝術——對不同資料做數千次完全相同的運算——好讓繪圖處理器龐大的平行性對它放手施展。

GPU 有數千個小型算術單元,為吞吐量而非低延遲而組織:它靠同時讓數萬條執行緒在途中、並在其他執行緒停頓時立刻切換到一條就緒的,來容忍漫長的記憶體等待。它的執行模型是 SIMT(單指令多執行緒):執行緒以鎖步群組執行(CUDA——主流程式框架——中 32 條為一個 warp),全都對不同資料執行同一條指令。當每條執行緒做同樣的事時這很美妙,當它們發散時則浪費——若一個 warp 裡有些執行緒走 if 分支、有些不走,硬體會輪流跑兩條路徑,故大量分支會扼殺 GPU 效能。GPU 也有自己的記憶體階層,包括一塊由程式設計者親手管理、小而快的晶片上「共享記憶體」,這是 GPU 對快取分塊的回應。一項關鍵成本是把資料搬過 CPU 與 GPU 記憶體間相對較慢的連結,若你把資料來回擺渡,這可能主宰一切。

GPU 在科學計算核心的那些核心上大放異彩:稠密線性代數(矩陣乘法完美對應到規則、高強度、所有執行緒一致的模式)、網格上的模板掃描(每個格點由一條獨立執行緒更新)、以及 FFT——全都是規則、資料平行、高算術強度的工作。它們在不規則、多分支、追指標、或低平行的計算上吃力。誠實的總結:對於對的問題,GPU 能交付比 CPU 多一個數量級的浮點運算與頻寬,但前提是工作大規模且一致地平行、資料留駐在裝置上、且演算法避開分支發散。它是吞吐量,不是免費的午餐。

對一個百萬格網格做五點模板掃描,每格指派一條 GPU 執行緒;全部一百萬次更新都獨立且相同,故以大規模平行鎖步執行,核心逼近 GPU 的尖峰頻寬。反觀帶資料相依分支的遞迴樹走訪則對應得很糟:一個 warp 裡的執行緒不斷發散,GPU 最後可能比 CPU 還慢。

GPU 在規則、一致、資料平行的核心上勝出;多分支的不規則程式擊敗 SIMT。

「GPU 快 100 倍」這種標題通常是對未最佳化的單一 CPU 核心、而非調校過的多核 CPU 的比較;真實程式誠實的加速往往更像 3 到 10 倍。而 CPU 與 GPU 記憶體間的資料傳輸可能把好處完全抹掉——若核心很快、你卻每一步都把資料拷進拷出,定你速度的是那條連結而非 GPU。

又称
GPGPUaccelerator computingCUDAGPU 加速計算通用 GPU 運算