总和3D矩阵cuda

时间:2012-03-30 10:09:28

标签: c cuda gpu gpu-programming

我需要进行如下计算:A [x] [y] = sum {从z = 0到z = n} {B [x] [y] [z] + C [x] [y] [z ]},其中矩阵A的维度为[height] [width],矩阵为B,C的维度为[height] [width] [n]。

使用以下内容将值映射到内存:

index = 0;
for (z = 0; z<n; ++z)
    for(y = 0; y<width; ++y)
        for(x = 0; x<height; ++x) {
            matrix[index] = value;
            index++;
        }

Q1:这个Cuda内核可以吗?

idx = blockIdx.x*blockDim.x + threadIdx.x;
idy = blockIdx.y*blockDim.y + threadIdx.y;

for(z=0; z<n; z++){
    A[idx*width+idy] += B[idx*width+idy+z*width*height] + C[idx*width+idy+z*width*height];
}

Q2:这是一种更快速的计算方法吗?

idx = blockIdx.x*blockDim.x + threadIdx.x;
idy = blockIdx.y*blockDim.y + threadIdx.y;
idz = blockIdx.z*blockDim.z + threadIdx.z;

int  stride_x = blockDim.x * gridDim.x;
int  stride_y = blockDim.y * gridDim.y;
int  stride_z = blockDim.z * gridDim.z;

while ( idx < height && idy < width && idz < n ) {
    atomicAdd( &(A[idx*width+idy]), B[idx*width+idy+idz*width*height] + C[idx*width+idy+idz*width*height] );
    idx += stride_x;
    idy += stride_y;
    idz += stride_z;
} 

3 个答案:

答案 0 :(得分:2)

第一个内核没问题。但我们尚未合并对矩阵BC的访问权限。

至于第二核心功能。你有数据竞争导致不仅一个线程有能力写入A[idx*width+idy]地址。您需要进行额外的同步,例如AttomicAdd

至于一般问题: 我认为实验表明它更好。这取决于您拥有的典型矩阵大小。请记住Fermi上的最大线程块大小&lt; 1024并且如果矩阵具有大尺寸,则可以创建许多线程块。通常它更慢(有许多线程块)。

答案 1 :(得分:2)

ArrayFire中的简单:

array A = randu(nx,ny,nz);
array B = sum(A,2); // sum along 3rd dimension
print(B);

答案 2 :(得分:1)

Q1:用你知道答案的矩阵进行测试

备注:使用非常大的矩阵时可能会遇到问题。使用具有适当增量的while循环。 Cuda by Example与往常一样是参考书。

可以在此处找到实现嵌套循环的示例:For nested loops with CUDA。有一个while循环实现。

marina.k关于比赛状况是正确的。这将有利于方法一,因为原子操作往往会减慢代码。