关于使用dim3设置CUDA内核中的线程数,我需要进行一些清理。

我在1D浮点数组中有一个图像,该图像通过以下方式复制到设备中:

checkCudaErrors(cudaMemcpy( img_d, img.data, img.row * img.col * sizeof(float), cudaMemcpyHostToDevice));

现在,我需要设置网格和块大小来启动内核:
dim3 blockDims(512);
dim3 gridDims((unsigned int) ceil(img.row * img.col * 3 / blockDims.x));
myKernel<<< gridDims, blockDims>>>(...)

我想知道:在这种情况下,由于数据是一维的,所以如果我使用dim3结构是否重要?使用上的任何好处
unsigned int num_blocks = ceil(img.row * img.col * 3 / blockDims.x));
myKernel<<<num_blocks, 512>>>(...)

反而?

另外,我的理解是正确的,当使用dim3时,我将在内核中使用2个索引引用线程ID:
int x = blockIdx.x * blockDim.x + threadIdx.x;
int y = blockIdx.y * blockDim.y + threadIdx.y;

当我不使用dim3时,我将只使用一个索引?

非常感谢你,

最佳答案

在内存中安排数据的方式与配置内核线程的方式无关。

内存始终是一维连续的字节空间。但是,访问模式取决于您如何解释数据以及如何通过1D,2D和3D线程块访问数据。



块和网格也会发生同样的情况。

欲了解更多信息,请访问:http://docs.nvidia.com/cuda/cuda-c-programming-guide/#dim3

因此,在两种情况下:dim3 blockDims(512);myKernel<<<num_blocks, 512>>>(...),您将始终可以访问threadIdx.y和threadIdx.z。

由于线程ID从零开始,因此您还可以使用y维将内存位置计算为行主要顺序:

int x = blockIdx.x * blockDim.x + threadIdx.x;
int y = blockIdx.y * blockDim.y + threadIdx.y;

int gid = img.col * y + x;

因为blockIdx.ythreadIdx.y将为零。

总而言之,如果您使用dim3结构,这很重要。我会很清楚地定义了线程的配置,并且1D,2D和3D访问模式取决于您如何解释数据以及如何通过1D,2D和3D线程块访问数据。

关于CUDA块/网格尺寸: when to use dim3?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31141541/

10-08 22:02