我需要进行如下计算: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;
}
答案 0 :(得分:2)
第一个内核没问题。但我们尚未合并对矩阵B
和C
的访问权限。
至于第二核心功能。你有数据竞争导致不仅一个线程有能力写入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关于比赛状况是正确的。这将有利于方法一,因为原子操作往往会减慢代码。