資料層級平行:SIMD、向量與 GPU

主機-裝置資料傳輸(host-device data transfer)

想像雇用一支住在遙遠島上、一千人的工班。他們能平行做出驚人的工作量——但他們需要的每一點材料都得先用船運過去,每件成品也都得運回來。若工作龐大,這些船程只是小小的額外開銷;若工作微小,你花在裝卸船上的時間比工作還多。主機-裝置資料傳輸就是那些船程:GPU(裝置)有自己分開的記憶體,在它能運算前,資料必須從 CPU 的記憶體(主機)跨過兩者之間的連線複製過去,事後再把結果複製回來。

具體說,CPU 與 GPU 通常有實體上分開的記憶體,以一條匯流排(如 PCI Express)相連。典型的 GPU 工作有四個階段:在裝置上配置記憶體、把輸入資料主機到裝置複製、啟動運算的核心程式,再把結果裝置到主機複製。那條匯流排有真實而有限的頻寬——遠低於 GPU 自己內部的記憶體頻寬——而且每次傳輸還有固定的起始延遲,所以許多次微小傳輸遠比一次大傳輸糟。這就是為什麼限制真實 GPU 程式的,往往是資料搬移的成本,而非算術。

每個 GPU 初學者都會吃過苦頭才學到的誠實教訓:傳輸可能抵銷加速。一個在 GPU 上快 50 倍的運算,若把資料來回複製比整件事在 CPU 上做還久,就不算贏——對小型或傳輸繁重的問題,GPU 是淨虧。標準解法是:把資料搬一次、讓它跨許多核心程式常駐在裝置上(攤分這趟船程);把傳輸與運算重疊,讓船航行的同時工班在工作;以及每傳一位元組就做夠多的算術(高算術強度),使這趟船程值回票價。判斷把工作卸載到裝置上是否划算時,永遠把傳輸算進去;忽略它是經典的初學者錯誤。

在 GPU 上把 10,000 個數字平方:平方本身快到不行,但你得把 40 KB 複製過去、40 KB 複製回來。複製加上它的起始延遲可能遠超過運算,所以這件小工作在 GPU 上比在 CPU 上慢。同一個核心程式用在 10,000 個稠密矩陣上、資料被大量重用時,就輕鬆獲勝,因為傳輸被龐大的算術攤分掉了。

主機與裝置之間的匯流排是任何核心程式都躲不掉的瓶頸;決定卸載前先把傳輸算進去。

不含資料傳輸而量到的 GPU 加速是虛構的。對小型或傳輸繁重的問題,主機-裝置複製的代價可能超過運算,讓 GPU 變成淨虧;把資料常駐在裝置上、並重疊傳輸來攤分它。

又称
host-to-device copyPCIe transferdata movement to the GPU主機到裝置複製PCIe 傳輸