CUDA 學習優化思路

2021-08-08 16:03:44 字數 2820 閱讀 3531

參考

cpu中memory<—>l3 cache傳輸頻寬為20gb/s, 除以64bytes/line得到傳輸記錄速度約300m line/s,約為300m*8= 2.4g double/s. 一般地,浮點數操作需要兩個輸入+1個輸出,那麼loading 3個數(3 lines)的代價為 100mflops。如果乙個line中的全部8個variables都被用到,那麼每秒浮點操作可以達到800mflops。而cpu工作站典型為10 gflops。這就要靠時間區域性性來重用資料了。

kepler gpu的cache line通常為128bytes(32個float or 16個double)。

資料傳輸頻寬最高250gb/s

smx的l2 cache統一1.5mb,l1 cache / shared memory有64kb

沒有cpu中的全域性快取一致性,所以幾乎沒有兩塊block更新相同的全域性陣列元素。

gpu對浮點數的操作速度可達1tflops。和上面cpu的計算類似,gpu中memory<—>l2cache傳輸頻寬為250gb/s, 除以128bytes/line得到傳輸記錄速度約2g line/s,約為2g*16= 32g double/s. 一般地,浮點數操作需要兩個輸入+1個輸出,那麼loading 3個數(3 lines)的代價為 670mflops。如果乙個line中的全部16個variables都被用到,那麼每秒浮點操作可以達到11gflops。

這樣的話每進行一次資料到device的傳輸需要45flops(45次浮點操作)才能達到500gflops. 所以很多演算法基本上不是卡在計算瓶頸,而是傳輸頻寬。

5.1 global arrays

global arrays:

儲存在/占用device memory

由host code(非kernel部分code)宣告

一直存在,直到被host code釋放

因為所有block執行順序不定,所以如果乙個block修改了乙個陣列元素,其他block就不能再對該元素進行讀寫

5.2 global variables

宣告前加識別符號device,表示變數要放在device上了 e.g.deviceint reduction_lock=0;

shared(見4.6)和constant(見4.3)中至多有乙個跟在device後面同時使用,標明用哪塊memory空間,如果這兩個都沒寫,則:

變數可以被grid內的所有threads讀寫

也可以定義為array,但是必須指定size

可以在host code中通過以下函式讀寫:

1. cudamemcpytosymbol;

2. cudamemcpyfromsymbol;

3. cudamemcpy + cudagetsymboladdress

5.4 register

預設乙個kernel中的所有內部變數都存在register中

64k 32-bit registers per smx

up to 63 registers per thread (up to 255 for k20 / k40)

這時有64k/63 = 1024個threads (256個threads for k20 / k40)

up to 2048 threads (at most 1024 per thread block)

這時每個thread有32個register

not much difference between 「fat」 and 「thin」 threads

如果程式需要更多的register呢?就「spill over」到l1 cache,這樣訪問速度就慢了,我們要盡量避免spill

5.5 local array

指kernel code中宣告的陣列。

簡單情況下,編譯器會將小陣列float a[3]轉換成3個標量registers:a0,a1,a2作處理

複雜的情況,會將array放到l1(16kb),只能放4096個32-bit的變數,如果有1024個執行緒,每個執行緒只能分配放4個變數。

5.6 shared memory

前面加識別符號sharede.g.sharedint x_dim;

要占用thread block的shared memory space.

要比global memory快很多,所以只要有機會就把global memory整成shared memory

與block同生死

thread block內所有threads共用(可讀可寫)

啥時侯用呢?當所有threads訪問都是同乙個值的時候,這樣就避免用register了

kepler gpu給l1 cache + shared memory總共64kb,可以分為16+48,32+32,48+16;這個split可以通過cudafuncsetcacheconfig()或cudadevicesetcacheconfig()設定,預設給shared memroy 48kb。這個具體情況看程式了。

參考:cuda c programming guide

different memory and variable types

cuda 安裝與配置

cuda除錯工具——cuda gdb

gpu工作方式

fermi 架構***(gpu繼承了fermi的很多架構特點)

gtx460架構

CUDA學習3 優化部分

基本概念 記憶體延遲掩藏 這裡我們假設乙個warp中線程數為2 實際不一定,如tesla為32個 有兩種規約的方式,左邊這種是採取鄰接的配對方式,右邊這種採用的是交錯的配對方式。從圖中我們可以看出,如果採用右邊這種配對方式,那麼在第一次配對完成之後我們就可以釋放出一半的warp,效能相比第一種方式有...

CUDA分支優化

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

CUDA 學習(二十) 優化策略5 演算法

一 概述 如果要考慮演算法,我們需要先思考如下問題 1 如何將問題分解成塊或片,然後如何將這些塊分解成執行緒 2 執行緒如何訪問資料以及產生什麼樣的記憶體模式 3 演算法總共要執行多少工作以及序列化的實現方法有何顯著不同 二 排序 可用的排序演算法有很多,其中有一些可以輕鬆 高效地在gpu 上實現,...