关于使用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>>>(...)
我想知道:在这种情况下,由于数据是1D,如果我使用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时,我只会使用一个索引?
非常感谢,
答案 0 :(得分:3)
在内存中排列数据的方式与您配置内核线程的方式无关。
内存始终是一维连续的字节空间。但是,访问模式取决于您如何解释数据以及如何通过1D,2D和3D线程块访问它们。
dim3
是基于uint3的整数向量类型,用于指定维度。定义dim3类型的变量时,任何未指定的组件都会初始化为1。
块和网格也是如此。
阅读详情: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线程块访问它们。