2012-04-26 87 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)