CUDA程式設計(八)樹狀加法

2021-09-30 14:42:03 字數 2351 閱讀 7012

那麼這個單執行緒的加法部分如何解決呢?我們知道gpu上的程式只有並行才能發揮其優勢,所以我們自然想到這個加法能不能並行呢?答案當然是可行的,我們可以利用樹狀加法的方式將加法並行,這也體現了我們之前提到的,乙個優秀的cuda程式是需要乙個優秀的演算法為基礎的。

我們傳統的加法 a + b + c + d ,只能在乙個執行緒上進行,但是我們也很容易想到,如果把加法分成多步執行,比如先算 a+b,c+d,再把他們的結果相加,通過這樣的方式我們就可以把任務分開,也就是可以並行了,這就是樹狀加法:

通過這種方式我們就可以把256個數的加法進行並行了。

上圖是樹狀加法的乙個示意圖,示意圖中第一排每乙個格仔就是乙個執行緒的結果,儲存在shared,暫且把shared[0]簡寫為 sh0,我們可以清楚的看到計算的過程:

sh0=sh0+sh1, sh2=sh2+sh3, sh4=sh4+sh5...

同步sh0=sh0+sh2;sh4=sh4+sh6...

同步...

最後結果在sh0裡

其實樹狀加法可以寫成乙個很簡單的while迴圈:

while(offset

< thread_num)

offset += offset;

mask = offset + mask;

__syncthreads(); }

下面我們就來看看這個while迴圈:

注意& 按位「與」,只有1&1 = 1

tid=0時,mask = 1,0&1=0,所以shared[0] = sh0 + sh1,完成第一步的前兩個相加。

tid=1時,mask = 1,1&1=1,不作運算。

tid=2時,mask = 1,10&01 = 00,所以shared[2] = sh2 + sh3

tid=3時,mask = 1,11&01 = 01,不作運算。

…可以看出來這是第一層的計算

同步之後第二層:

offset=1+1=2,mask=2+1=3;

tid=0時,mask = 3,0&11=0,所以shared[0] = sh0 + sh2,完成第二步的前兩個相加。

tid=1時,mask = 3,1&11=1,不作運算。

tid=2時,mask = 3,10&11 = 10,不作運算。

tid=3時,mask = 3,11&11 = 01,不作運算。

tid=4時,mask = 3,100&011 = 000,所以shared[4] = sh4 + sh6

後面都以此類推,直到offset 大於等於執行緒數就跳出了

最終的結果就在shared[0]內,所以下一步用執行緒0把結果儲存就ok了:

if(tid == 0)
所以比起上一版的程式,我們只用改動核函式裡面的加和部分就ok了,下面是改好的核函式:

核函式:

// __global__ 函式 (gpu上執行) 計算立方和

__global__ static

void sumofsquares(int *num, int* result, clock_t* time)

//同步 保證每個 thread 都已經把結果寫到 shared[tid] 裡面

__syncthreads();

//樹狀加法

int offset = 1, mask = 1;

while (offset < thread_num)

offset += offset;

mask = offset + mask;

__syncthreads();

}//計算時間,記錄結果,只在 thread 0(即 threadidx.x = 0 的時候)進行,每個 block 都會記錄開始時間及結束時間

if (tid == 0)

}

執行結果:

我們看到比起上一次沒用樹狀加法的144185個週期,這次只用了133738個週期,總的來說這個結果還是非常不錯的,甚至和完全不在gpu上加和的程式速度差不多,這是因為,在完全不在 gpu 上進行加總的版本,寫入到 global memory 的資料數量很大(8192 個數字),這對效率也會有影響。所以,這一版程式不但在 cpu 上的運算需求降低,在 gpu 上也能跑的更快~

希望我的部落格能幫助到大家~

CUDA之並行演算法系列(一)樹狀加法

我們傳統的加法 a b c d 只能在乙個執行緒上進行,但是我們也很容易想到,如果把加法分成多步執行,比如先算 a b,c d,再把他們的結果相加,通過這樣的方式我們就可以把任務分開,也就是可以並行了,這就是樹狀加法 通過這種方式我們就可以把256個數的加法進行並行了。上圖是樹狀加法的乙個示意圖,示...

CUDA C程式設計向量加法 第3章 CUDA 簡介

大規模並行處理器程式設計實戰 學習,其他章節關注專欄cuda c 這章主要以 向量加法 vector add 為切入點,講述了如何把乙個 c 語言向量加法 改寫為 cuda擴充套件的c語言向量加法。傳統向量加法是通過迴圈實現的 cuda向量加法是通過多執行緒控制的cuda加法並行實現的,即同時開啟n...

CUDA程式設計

cuda目前支援linux和windows作業系統。進行cuda開發需要依次安裝驅動 toolkit sdk三個軟體。在 安裝目錄 c src目錄下有很多的例程可以進行學習。cuda 的核心有三個重要抽象概念 執行緒組層次結構 共享儲存器 遮蔽同步 barrier synchronization 可...