天天看點

《CUDA C程式設計權威指南》——3.3 并行性的表現

本節書摘來自華章計算機《cuda c程式設計權威指南》一書中的第3章,第3.3節,作者 [美] 馬克斯·格羅斯曼(max grossman),譯 顔成鋼 殷建 李亮,更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視。

為更好地了解線程束執行的本質,将使用不同的執行配置分析下述的summatrixon-gpu2d核函數。使用nvprof配置名額,可以有助于了解為什麼有些網格/塊的維數組合比其他的組合更好。這些練習會提供網格和塊的啟發式算法,這是cuda程式設計人員必備的技能。

二維矩陣求和的核函數如下所示:

《CUDA C程式設計權威指南》——3.3 并行性的表現
《CUDA C程式設計權威指南》——3.3 并行性的表現

在每個次元,用16 384個元素确定一個大矩陣:

《CUDA C程式設計權威指南》——3.3 并行性的表現

下面的代碼段使線程塊的維數可以從指令行中進行配置:

《CUDA C程式設計權威指南》——3.3 并行性的表現

從wrox.com上可以下載下傳summatrix.cu,在該檔案中可以找到這個示例的完整代碼。使用下面的指令編譯代碼。

《CUDA C程式設計權威指南》——3.3 并行性的表現

在接下來的部分,将使用生成的summatrix對塊和網格配置執行試驗。

首先,需要生成一個參考結果作為性能基準。為此,要先測試一組基礎線程塊的配置,尤其是大小為(32,32),(32,16),(16,32)和(16,16)的線程塊。前面介紹過,summatrix接收線程塊配置的x維作為它的第一個參數,接收線程塊配置的y維作為它的第二個參數。通過用适當的指令行參數調用summatrix測試各種線程塊配置。

在tesla m2070上輸出以下結果:

《CUDA C程式設計權威指南》——3.3 并行性的表現

比較這些結果可以看到,最慢的性能是第一個線程塊配置(32,32)。最快的是第二個線程塊配置(32,16)。這樣可以推斷出,第二種情況比第一種情況有更多的線程塊,是以它的并行性更好。這個理論可以用nvprof和achieved_occupancy名額來驗證。一個核心的可實作占用率被定義為:每周期内活躍線程束的平均數量與一個sm支援的線程束最大數量的比值。結果總結如下(注意,如果系統中有多個gpu,可以用--devices指令行選項指揮nvprof從特定的裝置中擷取配置資訊):

《CUDA C程式設計權威指南》——3.3 并行性的表現

從結果中可以觀察到兩件事:

因為第二種情況中的塊數比第一種情況的多,是以裝置就可以有更多活躍的線程束。其原因可能是第二種情況與第一種情況相比有更高的可實作占用率和更好的性能。

第四種情況有最高的可實作占用率,但它不是最快的,是以,更高的占用率并不一定意味着有更高的性能。肯定有其他因素限制gpu的性能。

在summatrix核心(c[idx]=a[idx]+b[idx])中有3個記憶體操作:兩個記憶體加載和一個記憶體存儲。可以使用nvprof檢測這些記憶體操作的效率。首先,用gld_throughput名額檢查核心的記憶體讀取效率,進而得到每個執行配置的差異:

《CUDA C程式設計權威指南》——3.3 并行性的表現

第四種情況中的加載吞吐量最高,第二種情況中的加載吞吐量大約是第四種情況的一半,但第四種情況卻比第二種情況慢。是以,更高的加載吞吐量并不一定意味着更高的性能。第4章介紹記憶體事務在gpu裝置上的工作原理時将會具體分析産生這種現象的原因。

接下來,用gld_efficiency名額檢測全局加載效率,即被請求的全局加載吞吐量占所需的全局加載吞吐量的比值。它衡量了應用程式的加載操作利用裝置記憶體帶寬的程度。結果總結如下:

《CUDA C程式設計權威指南》——3.3 并行性的表現

從上述結果可知,最後兩種情況下的加載效率是最前面兩種情況的一半。這可以解釋為什麼最後兩種情況下更高的加載吞吐量和可實作占用率沒有産生較好的性能。盡管在最後兩種情況下正在執行的加載數量(即吞吐量)很多,但是那些加載的有效性(即效率)是較低的。

注意,最後兩種情況的共同特征是它們在最内層維數中塊的大小是線程束的一半。如前所述,對網格和塊啟發式算法來說,最内層的維數應該總是線程束大小的倍數。第4章将讨論半個線程束大小的線程塊是如何影響性能的。

從前一節可以總結出,一個塊的最内層維數(block.x)應該是線程束大小的倍數。這樣能極大地提高了加載效率。你可能對以下問題仍然很好奇:

調整block.x會進一步增加加載吞吐量嗎

有其他方法可以增大并行性嗎

現在已經建立了一個性能基準,可以通過測試summatrix使用更大範圍的線程配置來回答這些問題:

《CUDA C程式設計權威指南》——3.3 并行性的表現

從這些結果中可以總結出以下規律:

最後一次的執行配置塊的大小為(256,8),這是無效的。一個塊中線程總數超過了1 024個(這是gpu的硬體限制)。

最好的結果是第四種情況,塊大小為(128,2)。

第一種情況中塊大小為(64,2),盡管在這種情況下啟動的線程塊最多,但不是最快的配置。

因為第二種情況中塊的配置為(64,4),與最好的情況有相同數量的線程塊,這兩種情況應該在裝置上顯示出相同的并行性。因為這種情況相比(128,2)仍然表現較差,是以你可以得出這樣的結論:線程塊最内層次元的大小對性能起着的關鍵的作用。這正重複了前一節中總結的結論。

在所有其他情況下,線程塊的數量都比最好的情況少。是以,增大并行性仍然是性能優化的一個重要因素。

你可能會想,線程塊最少的那些示例應該顯示出較低的可實作占用率,線程塊最多的那些例子應該顯示出較高的可實作占用率。這個理論可以用nvprof檢測achieved_occu-pancy名額來驗證一下:

《CUDA C程式設計權威指南》——3.3 并行性的表現

從上面的結果可以得到,第一種情況(64,2)在所有例子中可實作占用率最低,但它的線程塊是最多的。這種情況線上程塊的最大數量上遇到了硬體限制。

第四種情況(128,2)和第七種情況(256,2),擁有最高的性能配置,有幾乎相同的可實作占用率。在這兩種情況下,通過将block.y設定為1來增大塊間并行性,觀察性能将如何變化。這使得每個線程塊大小減少了,引起了更多的線程塊被啟動來處理相同數量的資料。這樣做會産生以下結果:

《CUDA C程式設計權威指南》——3.3 并行性的表現

到目前為止,這些配置能産生最佳的性能。特别是(256,1)的塊配置優于(128,1)。可以使用以下的指令檢視可實作占用率、加載吞吐量和加載效率:

《CUDA C程式設計權威指南》——3.3 并行性的表現

結果如下:

《CUDA C程式設計權威指南》——3.3 并行性的表現

值得注意的是,最好的執行配置既不具有最高的可實作占用率,也不具有最高的加載吞吐量。從這些實驗中可以推斷出,沒有一個單獨的名額能直接優化性能。我們需要在幾個相關的名額間尋找一個恰當的平衡來達到最佳的總體性能。

《CUDA C程式設計權威指南》——3.3 并行性的表現
《CUDA C程式設計權威指南》——3.3 并行性的表現

繼續閱讀