理解cuda並行程序的規約思想


並行程序的開發有其不同於單核程序的特殊性,算法是重中之重。根據不同業務設計出不同的並行算法,直接影響到程序的效率。因此,如何設計並行程序的算法,似乎成為並行
編程的最大難點。觀其算法,包括cuda sdk的例子和網上的牛人,給出的一些例子,以矩陣和矢量處理為主,深入點的包括fft和julia等數學公式,再高級一點的算是圖形處理方
面的例子。學習這些算法的思想,免不了有自己的一點點總結。
之前學習過omp編程,結合現在的cuda,我覺得要理解並行編程,首先理解划分和規約這兩個概念。也許你的算法學的更加扎實。划分是《算法》里面的一個重要思想,將一個大
的問題或任務,分解成小問題小任務,各個擊破,最后歸並結果;規約是《cuda**》書上介紹的一個入門的重要思想,規約算法(reduction)用來求連加、連乘、最值等,應用廣
泛。每次循環參加運算的線程減少一半。
不管算法的思想如何花樣,萬變不離其中的一點--將一個大的任務分解成小的任務集合,分解原則是粒度合適盡量小、數據相關性盡量小。如此而已。因為,我們用GPU是為了
加速,要加速必須提高執行任務的並行度!明白這個道理,那么我們將絞盡腦汁地去想方設法分析自己手上的任務,分解、分解、分解!
這里拿規約來說事情,因為,規約這個東西,似乎可以拿來單做9*9乘法表來熟悉,熟悉了基礎的口訣,那么99*99的難題也會迎刃而解。
ex:矢量加法,要實現N=64*256長度的矢量的累加和。假設a+b計算一次耗時t。

cpu計算:
顯然單核的話需要64*256*t。我們容忍不了。

gpu計算:
最初的設想,我們如果有個gpu能同時跑N/2個線程,我們這N/2個線程同時跑,那么不是只需要t時間就能將N個數相加編程N/2個數相加了嗎?對的。這一輪我們用了t時間;
接着的想法,我們不斷的遞歸這個過程,能發現嗎?第二輪,我們用N/2/2個線程同時跑,剩下N/2/2個數相加,這一輪我們同樣用了t時間;
一直這樣想下去吧,最后一輪,我們用了1個線程跑,剩下1個數啦,這就是我們的結果!!!
每一輪時間都為t,那么理想情況,我們用了多少輪這樣的計算呢?
計算次數=log(N)=6*8=48,對的,只用了48輪,也就是說,我們花了48*t的時間!

規約就是這樣,很簡單,很好用,我們且不管程序后期的優化,單從這個算法分析上來說,從時間復雜度N降到了logN,這在常規算法上,要提高成這樣的效率,是不得了的,
這是指數級別的效率提高!所以,你會發現,GPU有CPU無法取代的得天獨厚的優勢————處理單元真心多啊!

規約求和的核函數代碼如下:
__global__ void RowSum(float* A, float* B){
    int bid = blockIdx.x;
    int tid = threadIdx.x;

    __shared__ s_data[128];
   
    //read data to shared memory
    s_data[tid] = A[bid*128 + tid];
    __synctheads();        //sync

    for(int i=64; i>0; i/=2){
        if(tid<i)
            s_data[tid] = s_data[tid] + s_data[tid+i] ;
        __synctheads();
    }
    if(tid==0)
        B[bid] = s_data[0];
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM