关于使用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.y
和threadIdx.y
将为零。总而言之,如果您使用dim3结构,这很重要。我会很清楚地定义了线程的配置,并且1D,2D和3D访问模式取决于您如何解释数据以及如何通过1D,2D和3D线程块访问数据。
关于CUDA块/网格尺寸: when to use dim3?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31141541/