並行化應用程式:
確定了熱點並完成了設定目標和期望的基本練習後,開發人員需要對**進行並行化。 根據原始**,這可以像呼叫現有的gpu優化庫(如cublas,cufft或thrust)一樣簡單,也可以像向並行編譯器新增一些預處理器指令那樣簡單。
另一方面,一些應用程式的設計需要一些重構來展現其固有的並行性。 由於即使將來的cpu架構也需要公開這種並行性以改進或簡單地維持順序應用的效能,因此cuda並行程式語言系列(cuda c / c ++,cuda fortran等)旨在盡可能簡化這種並行性的表達,同時使支援cuda的gpu能夠在最大並行吞吐量的情況下執行。
入門:並行化順序**有幾個關鍵策略。 儘管如何將這些策略應用到特定應用程式的細節是乙個複雜且具有問題特徵的主題,但無論我們是否並行化執行在多核cpu上的**或在cuda gpu上使用的**,此處列出的一般主題都適用。
並行庫:
並行化應用程式最直接的方法是利用現有的庫,代表我們利用並行體系結構。 cuda工具包包括許多已針對nvidia cuda gpu進行微調的庫,例如cublas,cufft等。
這裡的關鍵是,庫在與應用程式的需求相匹配時最有用。 例如,已經使用其他blas庫的應用程式通常可以很容易地切換到cublas,而對於線性代數幾乎沒有的應用程式對cublas幾乎沒有用處。 其他cuda工具包庫也是如此:cufft具有類似於fftw等的介面。
還值得注意的是thrust庫,它是乙個類似於c ++標準模板庫的並行c ++模板庫。 thrust提供了豐富的資料並行基元集合,如掃瞄,排序和縮減,它們可以組合在一起以實現具有簡潔可讀源**的複雜演算法。 通過根據這些高階抽象描述您的計算,您可以為thrust提供自動選擇最有效的實現的自由。 因此,thrust可用於程式設計師生產力最重要的cuda應用程式的快速原型開發,以及堅固性和絕對效能至關重要的生產。
並行化編譯器:
順序**並行化的另一種常見方法是利用並行化編譯器。 通常這意味著使用基於指令的方法,程式設計師使用編譯指示或其他類似的符號向編譯器提供關於何處可以找到並行性的提示,而無需修改或修改底層**本身。 通過向編譯器公開並行性,指令允許編譯器執行將計算對映到並行體系結構的詳細工作。
openacc標準提供了一組編譯器指令,用於指定標準c,c ++和fortran中的**迴圈和區域,這些**應該從主機cpu解除安裝到附加的加速器(如cuda gpu)。 管理加速器裝置的細節由openacc啟用的編譯器和執行時隱式處理。
編碼揭示並行性:
對於需要超出現有並行庫或並行編譯器可提供的附加功能或效能的應用程式而言,並行程式語言(如cuda c / c ++)與現有的順序**無縫整合是必不可少的。
一旦我們在應用程式的配置檔案評估中找到熱點並確定自定義**是最好的方法,我們就可以使用cuda c / c ++將我們**的那部分內容的並行性暴露為cuda核心。 然後,我們可以將此核心啟動到gpu上,並檢索結果,而無需對我們的其他應用程式進行重大改寫。
當我們的應用程式的總執行時間的大部分花費在**的一些相對孤立的部分中時,這種方法是最直接的。 更難以並行化的是具有非常平坦的輪廓的應用程式 - 即,花費的時間相對均勻地分布在寬廣的**庫部分的應用程式。 對於後一種應用程式,可能需要一定程度的**重構來暴露應用程式中固有的並行性,但請記住,此重構工作將趨於惠及所有未來體系結構,cpu和gpu等,因此它非常值得 應該有必要的努力。
CUDA實踐指南(十六)
共享記憶體啟用塊中線程之間的協作。當乙個塊中的多個執行緒使用全域性記憶體中的相同資料時,共享記憶體只能用於從全域性記憶體訪問一次資料。共享記憶體還可以用來避免未合併的記憶體訪問,方法是從全域性記憶體中載入和儲存合併模式的資料,然後將其重新排列在共享記憶體中。除了儲存體衝突之外,共享記憶體中的變形對非...
CUDA實踐指南(十三)
裝置記憶體空間 cuda裝置使用多個記憶體空間,這些記憶體空間具有不同的特性,這些特性反映了它們在cuda應用程式中的不同用法 這些記憶體空間包括全域性,本地,共享,紋理和暫存器,如圖2所示 合併的訪問要求取決於裝置的計算能力,可以查閱cuda c程式設計指南中。在這些不同的記憶空間中,全域性記憶是...
CUDA實踐指南(九)
頻寬 頻寬 資料可以傳輸的速率 是效能最重要的門控因素之一。的幾乎所有變化都應該在它們如何影響頻寬的情況下進行。頻寬可能會因資料儲存的記憶體選擇,資料布局方式以及訪問順序以及其他因素而受到顯著影響。要準確測量效能,計算理論和有效頻寬非常有用。當後者遠低於前者時,設計或實現細節可能會降低頻寬,並且應該...