矩陣按行(列)求和CUDA並行算法設計

下載請點擊:矩陣按行(列)求和CUDA並行算法

 

通過矩陣按行求和與按列求和兩個示例介紹CUDA並行算法設計的思路,希望對大家有所幫助。很多公司CUDA工程師面試也會考察這個題目。

1.        矩陣按行求和

矩陣A[M][N],B[M];

B[i] =A[0]+A[1]+...+A[N-1];

串行代碼:

  #define A(i)(j)  A[(i)*N+(j)]

void sum_row(T *A,T*B,int M,int N)

{

     int i,j;

     T tmp;

     for(i=0; i<M; i++)

     {

              tmp=0;

              for(j=0; j<N; j++)

                       tmp += A(i)(j);

              B[i] = tmp;

     }

}

 

CUDA程序設計:

每個block處理一行數據的求和,M設置爲block數目,即

dim3 dimBlock(BLOCKSIZE, 1, 1);

dim3 dimGrid(M, 1, 1);

 

__global__ void sum_row_kernel(T*A,T *B,int M,int N)

{

     int i,j;

     T tmp;

     unsigned inttid =threadIdx.x;

     i = blockIdx.x;

     tmp=0;

     T sh_B[BLOCKSIZE];

     sh_B[tid] = 0;

     __syncthreads();

     for(j=tid; j<N; j+= BLOCKSIZE)

              tmp += A(i)(j);

     sh_B[tid] = tmp;

     __syncthreads();

    if (blockSize >= 512) {if (tid < 256) {sh_B[tid] =tmp = tmp +sh_B[tid + 256]; }__syncthreads();}

    if (blockSize >= 256) {if (tid < 128) {sh_B[tid] =tmp = tmp +sh_B[tid + 128]; }__syncthreads(); }

    if (blockSize >= 128) {if (tid < 64) {sh_B[tid] =tmp = tmp +sh_B[tid +  64]; }__syncthreads(); }

   

   

    if (tid < 32)

    {

                volatile float *smem = sh_B;

                if (BLOCKSIZE >=  64) { smem[tid] = tmp = tmp + smem[tid + 32]; }

                if (BLOCKSIZE >=  32) { smem[tid] = tmp = tmp + smem[tid + 16]; }

                if (BLOCKSIZE >=  16) { smem[tid] = tmp = tmp + smem[tid +  8]; }

                if (BLOCKSIZE >=   8) { smem[tid] = tmp = tmp + smem[tid +  4]; }

                if (BLOCKSIZE >=   4) { smem[tid] = tmp = tmp + smem[tid +  2]; }

                if (BLOCKSIZE >=   2) { smem[tid] = tmp = tmp + smem[tid +  1]; }


 

  }

   if(tid==0)

       B =sh_B[0];

 

}

備註:

1)  當M比較大,N比較小時,可以採用一個warp處理一行的方式;

2)  當M比較小,N比較大時,可以讓多個block處理一行的求和

以上的設計可以保證足夠多的線程數和block數,充分利用GPU資源。

 

2.        矩陣按列求和

矩陣A[M][N],B[N];

B[j] = A[0][j]+A[1][j]+...+A[M-1][j];

串行代碼:

  #define A(i)(j)  A[(i)*N+(j)]

void sum_col(T *A,T*B,int M,int N)

{

     int i,j;

     T tmp;

     for(j=0; j<N; j++)

     {

              tmp=0;

              for(i=0; i<M; i++)

                       tmp += A(i)(j);

              B[j] = tmp;

     }

}

 

CUDA程序設計:

每個線程處理一列數據的求和,N/threads設置爲block數目,即

dim3 dimBlock(BLOCKSIZE, 1, 1);

dim3 dimGrid((M+ BLOCKSIZE-1)/ BLOCKSIZE, 1, 1);

 

__global__ void sum_col_kernel(T*A,T *B,int M,int N)

{

     int i,j;

     T tmp;

     j = blockIdx.x*blockDim.x+ threadIdx.x;

     tmp=0;

     for(i=0; i<M; i++)

              tmp += A(i)(j);  //可以滿足合併訪問

     B[j] = tmp;

}

備註:

當M比較大,N比較小時,可以採用一個block處理一列的方式,然後對block內的值再求和

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章