2012-04-26 89 views
1

假設我有一個從MxN 2D矩陣轉換而來的一維數組,並且我想對每列進行並行化並執行一些操作。我如何爲每列分配一個線程?在CUDA中進行並行化,爲每列分配線程

例如,如果我有一個3×3矩陣:

1 2 3 

4 5 6 

7 8 9 

我要添加在取決於列#列中的每個數(因此第一列將加1,第二加2 .. ..),它變成:

1+1 2+1 3+1 

4+2 5+2 6+2 

7+3 8+3 9+3 

我該如何在CUDA中執行此操作?我知道如何將線程分配給數組中的所有元素,但我不知道如何將線程分配給每列。所以,我想要發送每一列(1,2,3)(4,5,6)(7,8,9)並進行操作。

回答

3

在您的示例中,您將基於該行添加數字。不過,你知道矩陣的行/列長度(你知道它是MxN)。你可以做的是一樣的東西:

__global__ void MyAddingKernel(int* matrix, int M, int N) 
{ 

    int gid = threadIdx.x + blockDim.x*blockIdx.x; 
    //Let's add the row number to each element 
    matrix[ gid ] += gid % M; 
    //Let's add the column number to each element 
    matrix[ gid ] += gid % N; 

} 

如果你想添加不同的號碼,你可以這樣做:

matrix[ gid ] += my_col_number_function(gid%N); 
+0

哦,謝謝你的回覆,但是如果我想在每一行中將每個元素從右向左移動而不是添加?因此,在我的例子中,第一行(1 2 3)將變成(2 3 3)[保持最後一個元素相同],(4 5 6)變成(5 6 6)並且(7 8 9)變成(8 9 9)?它可能像你顯示的加法操作一樣嗎?謝謝! – overloading 2012-04-26 20:07:03

+0

在這種情況下,就像 'matrix [gid] =(gid%N)?矩陣[gid + 1]:矩陣[gid];' 可能工作。 – limes 2012-04-26 20:19:25

+0

模運算符是在GPU上的昂貴的操作,儘量避免它! – djmj 2012-04-27 00:23:21

2

使用更好的網格佈局,以避免那些模運算。

對最新的Cuda中的64位範圍的行使用唯一的塊索引。

讓線程循環遍歷所有元素並添加唯一的線索索引!

如果計算的數據在塊(行)中唯一,特別是對於更復雜的計算,平鋪輸入數據是一種常用方法。

/* 
* @param tileCount 
*/ 
__global__ void addRowNumberToCells(int* inOutMat_g, 
    const unsigned long long int inColumnCount_s, 
    const int inTileCount_s) 
{ 

    //get unique block index 
    const unsigned long long int blockId = blockIdx.x //1D 
     + blockIdx.y * gridDim.x //2D 
     + gridDim.x * gridDim.y * blockIdx.z; //3D 

    /* 
    * check column ranges in case kernel is called 
    * with more blocks then columns 
    * (since its block wide following syncthreads are safe) 
    */ 
    if(blockId >= inColumnCount_s) 
     return; 

    //get unique thread index 
    const unsigned long long int threadId = blockId * blockDim.x + threadIdx.x; 

    /* 
    * calculate unique and 1 blockId 
    * maybe shared memory is overhead 
    * but it shows concept if calculation is more complex 
    */ 
    __shared__ unsigned long long int blockIdAnd1_s; 
    if(threadIdx.x == 0) 
     blockIdAnd1_s = blockId + 1; 
    __sycnthreads(); 


    unsigned long long int idx; 

    //loop over tiles 
    for(int i = 0; i < inTileCount_s) 
    { 
     //calculate new offset for sequence thread writes 
     idx = i * blockDim.x + threadIdx.x; 
     //check new index range in case column count is no multiple of blockDim.x 
     if(idx >= inColumnCount_s) 
      break; 
     inOutMat_g[idx] = blockIdAnd1_s; 
    } 

} 

例Cuda的2.0:

墊[131000] [1000]

必要blockCount =六萬五千五百三十五分之一十三萬一千= 2 blockDim.y四捨五入!

inTileCount_s = 1000/192 = 6四捨五入!

(192個每塊= 100佔用線程CUDA的2.0)

< <(65535,2,1),(192,1,1)>> addRowNumberToCells(墊子,1000,6)