第二篇:從 GPU 的角度理解並行計算


前言

  本文從使用 GPU 編程技術的角度來了解計算中並行實現的方法思路。

並行計算中需要考慮的三個重要問題

       1. 同步問題

       在操作系統原理的相關課程中我們學習過進程間的死鎖問題,以及由於資源共享帶來的臨界資源問題等,這里不做累述。

  2. 並發度

       有一些問題屬於 “易並行” 問題:如矩陣乘法。在這類型問題中,各個運算單元輸出的結果是相互獨立的,這類問題能夠得到很輕松的解決 (通常甚至調用幾個類庫就能搞定問題)。

       然而,若各個運算單元之間有依賴關系,那問題就復雜了。在 CUDA 中,塊內的通信通過共享內存來實現,而塊間的通信,則只能通過全局內存。

       CUDA 並行編程架構可以用網格 (GRID) 來形容:一個網格好比一只軍隊。網格被分成好多個塊,這些塊好比軍隊的每個部門 (后勤部,指揮部,通信部等)。每個塊又分成好多個線程束,這些線程束好比部門內部的小分隊,下圖可幫助理解:

       3. 局部性

       在操作系統原理中,對局部性做過重點介紹,簡單來說就是將之前訪問過的數據 (時間局部性) 和之前訪問過的數據的附近數據 (空間局部性) 保存在緩存中。

       在 GPU 編程中,局部性也是非常重要的,這體現在要計算的數據應當在計算之前盡可能的一次性的送進顯存,在迭代的過程中一定要盡可能減少數據在內存和顯存之間的傳輸,實際項目中發現這點十分重要的。

       對於 GPU 編程來說,需要程序猿自己去管理內存,或者換句話來說,自己實現局部性

並行計算的兩種類型

       1. 基於任務的並行處理

       這種並行模式將計算任務拆分成若干個小的但不同的任務,如有的運算單元負責取數,有的運算單元負責計算,有的負責...... 這樣一個大的任務可以組成一道流水線。

       需要注意的是流水線的效率瓶頸在於其中效率最低的那個計算單元

  2. 基於數據的並行處理

       這種並行模式將數據分解為多個部分,讓多個運算單元分別去計算這些小塊的數據,最后再將其匯總起來。

       一般來說,CPU 的多線程編程偏向於第一種並行模式,GPU 並行編程模式則偏向於第二種。

常見的並行優化對象

       1. 循環

       這也是最常見的一種模式,讓每個線程處理循環中的一個或一組數據。

       這種類型的優化一定要小心各個運算單元,以及每個運算單元何其自身上一次迭代結果的依賴性。

       2. 派生/匯集模式

       該模式下大多數是串行代碼,但代碼中的某一段可以並行處理。

       典型的情況就是某個輸入隊列當串行處理到某個時刻,需要對其中不同部分進行不同處理,這樣就可以划分成多個計算單元對改隊列進行處理 (也即派生),最后再將其匯總 (也即匯集)。

       這種模式常用於並發事件事先不定的情況,具有 “動態並行性”。

       3. 分條/分塊模式

       對於特別龐大的數據 (如氣候模型),可以將數據分為過個塊來進行並行計算。

       4. 分而治之

       絕大多數的遞歸算法,比如快速排序,都可以轉換為迭代模型,而迭代模型又能映射到 GPU 編程模型上。

       特別說明:雖然費米架構和開普勒架構的 GPU 都支持緩沖棧,能夠直接實現遞歸模型到 GPU 並行模型的轉換。但為了程序的效率,在開發時間允許的情況下,我們最好還是先將其轉換為迭代模型。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM