CUDA學習3 優化部分

2021-10-19 11:56:20 字數 3245 閱讀 1162

基本概念

記憶體延遲掩藏

這裡我們假設乙個warp中線程數為2(實際不一定,如tesla為32個),有兩種規約的方式,左邊這種是採取鄰接的配對方式,右邊這種採用的是交錯的配對方式。

從圖中我們可以看出,如果採用右邊這種配對方式,那麼在第一次配對完成之後我們就可以釋放出一半的warp,效能相比第一種方式有所提公升。

下面是**實現:

由於每個warp中的執行緒都是天然同步的,所以我們在設計演算法的時候最好不要讓他們產生分支(執行緒束分化)

同樣以上面的圖為例子來講述,左邊我們可以看到在第一輪配對之後就發生了執行緒束分化,也就是說對於同乙個warp中的執行緒,有的需要進行下一步的配對而有的則不需要,這樣就會產生效能的浪費。

而在右邊的圖里我們可以看到,在前面幾輪中,不會發生這樣子的執行緒束分化,同時後面的warp就可以被釋放出來進而進行其他的工作。

由於平行計算很多情況下我們是在gpu上進行的,但是這樣我們就有大量的資料傳輸要在cpu和gpu之間進行。

這時候通常情況下我們有三種方式進行優化:

組團傳輸

記憶體傳輸與計算時間重疊

global memory的延時 : 400-800 cycles

如果快取:warp的讀寫請求落到一級快取,只需一次傳輸transaction = # l1 line accessed

如果沒有快取:那麼就有一些合併的原則,比如下面這種

但是有兩種訪存模式不推薦

每個執行緒訪問很長的連續的一段空間

如果要跳著訪問,也就是訪問的步長很大,那麼就需要用到shared memory來進行優化了

shared memory 被劃分為很多個 banks

下面這個情況就沒有發生bank衝突:

而下面這個情況則發生了bank衝突:(一般情況下,有幾路的bank衝突就會讓效能下降幾倍)

實際上就是解決這個bank衝突的過程

由於矩陣轉置的過程中,讀入是按行訪問的,但是寫出卻要按列訪問,如果保持不變的話在寫入時就會發生bank衝突,這時候我們可以通過改變一下位置(+1即可)來避免這種衝突。

總結一下對資料平行計算的優化方式

使用shared memory時減少bank衝突

以g80為例,他有768個執行緒,8k個暫存器,16k個shared memory,8個block。

所以我們能把這麼多個執行緒分為8個執行緒塊,每塊放96個執行緒。但如果我們把這麼多個執行緒分為4個執行緒塊,每塊就要放192個執行緒。

假設每個block有256個執行緒,那麼 768 threads( 3 blocks),每個執行緒用 10 registers。而 512 threads( 2 blocks),每個執行緒用 11 registers。也就是說,如果每個執行緒要用11個暫存器,那麼剩下的執行緒就得等到下一批了,而剩下的暫存器保持空閒直到下一次被使用,這樣會造成效能的下降。我們將這種因為資源用量的增加而造成的並行性的急劇下降稱為performance cliff。

kernel啟動引數配置:

方法1:

方法2:

occupancy 佔用率

這裡預設一條算術指令需要2個時鐘週期

這裡第二個語句就是被插入進去的,因為第乙個語句和第三個語句的延遲比較大。

對於部分指令我們可以進行替換

避免double到float的型別自動轉換,因為這個轉換時多餘的操作

慢但是精度高的函式func()轉換為快但是精度低的函式__func()

for

(int k=

0; k

++k)

對於這個for迴圈,其實有很多多餘的東西,如每次都要 ++k 和 判斷k是否小於block_size 以及 訪存時位址的運算 等等。

這樣就有很多多餘的操作,所以我們可以通過迴圈展開來優化它。

//這裡假設block_size = 16,則可以展開為

pvalue +

= ms[ty][0

]* ns[0]

[tx]

+ ms[ty][1

]* ns[1]

[tx]+.

..ms[ty][15

]* ns[15]

[tx]

;

這樣我們就少了迴圈計數器更新、分支指令和位址運算指令。

當然,迴圈展開也可以自動實現,**如下:

#pragma unroll block_size

for(

int k=

0; k

++k)

但是,迴圈展開也有一些缺點,如可擴充套件性不強。

CUDA 學習優化思路

參考 cpu中memory l3 cache傳輸頻寬為20gb s,除以64bytes line得到傳輸記錄速度約300m line s,約為300m 8 2.4g double s.一般地,浮點數操作需要兩個輸入 1個輸出,那麼loading 3個數 3 lines 的代價為 100mflops。...

CUDA分支優化

標籤 cuda 分支優化 warpsm 2015 07 16 10 24 293人閱讀收藏 舉報 cuda 26 在cuda中,分支會極大的減弱效能,因為 沒有分支 因此只能讓束內線程在每個分支上都執行一遍,當然如果某個分支沒有執行緒執行,就可以忽略,因此要減少分支的數目。可以簡單的說 1.同乙個w...

cuda程式設計學習3 VectorSum

這個程式是把兩個向量相加 add dev a,dev b,dev c 第乙個引數n代表block的數量,第二個引數1代表每個block中thread的數量 tid blockidx.x blockidx是乙個內建變數,blockidx.x代表這是乙個2維索引 下面對這個程式做幾個變化,並指出相應的程...