我正在尝试将网格从1d扩展到2d网格。有没有办法做到这一点?
这是我目前的代码:
int idx = threadIdx.x + blockDim.x * blockIdx.x;
在#include
列表中,我有以下定义:
#define BLOCKS_PER_GRID 102
#define THREADS_PER_BLOCK 1024
答案 0 :(得分:1)
假设您希望每个块有1024个线程,则可以轻松地将块重新整形为2D。
32 x 32 = 1024;
所以你的块看起来像这样:
dim3 Block(32,32); //1024 threads per block. Will only work for devices of at least 2.0 Compute Capability.
我不知道您的确切要求是什么,但通常不修复块数(正如您在宏中定义的那样)。块数取决于输入数据大小,因此网格可以动态扩展。
根据您的情况,您有很多选项,但网格最接近的最佳尺寸为17 x 6
或6 x 17
。
dim3 Grid(17,6);
现在您可以使用以下参数调用内核:
kernel<<<Grid,Block>>>();
在内核中,线程的二维索引计算如下:
int xIndex = blockIdx.x * blockDim.x + threadIdx.x;
int yIndex = blockIdx.y * blockDim.y + threadIdx.y;
或者,如果您遵循行/列约定而不是x / y,则:
int row = blockIdx.y * blockDim.y + threadIdx.y;
int column = blockIdx.x * blockDim.x + threadIdx.x;
答案 1 :(得分:1)
您还可以拥有1维线程块的2D网格,以便绕过每网格尺寸65535个块的限制(对于pre-cc3.0设备)。这可能是一种更简单的方法,可以在不引入数据的二维数组表示的情况下,将基本的一维问题扩展到限制之外。
假设我们将DATA_ELEMENTS
参数定义为内核将处理的元素数(每个线程一个元素)。如果DATA_ELEMENTS
大于65535 * 1024,那么如果每个线程只处理1个元素,则无法使用1-D网格处理它们。
您可以保持THREADS_PER_BLOCK
参数相同。内核中的线程索引计算将更改为:
int idx = threadIdx.x + (blockDim.x * ((gridDim.x * blockIdx.y) + blockIdx.x));
您需要确保使用以下内容来调整内核计算:
if (idx < DATA_ELEMENTS){
(kernel code)
}
您的网格尺寸如下:
dim3 grid;
if (DATA_ELEMENTS > (65535*THREADS_PER_BLOCK)){ // create a 2-D grid
int gridx = 65535; // could choose another number here
int gridy = ((DATA_ELEMENTS+(THREADS_PER_BLOCK-1))/THREADS_PER_BLOCK)/gridx;
if ((((DATA_ELEMENTS+(THREADS_PER_BLOCK-1))/THREADS_PER_BLOCK)%gridx) != 0) gridy++;
grid.x=gridx;
grid.y=gridy;
grid.z=1;
}
else{ // create a 1-D grid
int gridx = (DATA_ELEMENTS+(THREADS_PER_BLOCK-1))/THREADS_PER_BLOCK;
grid.x=gridx;
grid.y=1;
grid.z=1;
}
你可以将你的内核启动为:
kernel<<<grid, THREADS_PER_BLOCK>>>(...);
解决此类问题的另一种方法是创建某个维度的一维网格(假设网格中的线程总数为NUM_THREADS_PER_GRID
),并让每个线程都在多个线程上工作数据元素数组中的元素,使用类似for循环或while循环的东西:
while (idx < DATA_ELEMENTS) {
(code to process an element)
idx += NUM_THREADS_PER_GRID
}
答案 2 :(得分:0)
我喜欢Robert的上述解决方案。我对他的第一个解决方案的唯一评论是,gridx
似乎应该使DATA_ELEMENTS > (65535*THREADS_PER_BLOCK)
尽可能小。65535*THREADS_PER_BLOCK + 1
。原因是,如果数据元素的数量为gridx
,而65535
为65535*2*THREADS_PER_BLOCK
,则会启动gridx
,因此几乎一半的线程将无效。如果{{1}}较小,则会有较少的线程无效。