我得到的是什么blockDim,但我有问题gridDim. Blockdim给出块的大小,但是什么gridDim?在互联网上它说明gridDim.x了x坐标中的块数.
我怎么知道是什么blockDim.x * gridDim.x给出的?
我怎么知道gridDim.xx行中有多少个值?
例如,请考虑以下代码:
int tid = threadIdx.x + blockIdx.x * blockDim.x;
double temp = a[tid];
tid += blockDim.x * gridDim.x;
while (tid < count)
{
if (a[tid] > temp)
{
temp = a[tid];
}
tid += blockDim.x * gridDim.x;
}
Run Code Online (Sandbox Code Playgroud)
我知道tid从0开始.代码然后有tid+=blockDim.x * gridDim.x.什么是tid现在这个手术后?
Rob*_*lla 84
blockDim.x,y,z 给出特定方向上块中的线程数gridDim.x,y,z 给出特定方向上网格中的块数blockDim.x * gridDim.x 给出网格中的线程数(在x方向,在这种情况下)块和网格变量可以是1,2或3维.处理1-D数据时,通常只创建1-D块和网格.
在CUDA文档中,这些变量在此处定义
特别是,当x维度中的总线程数(gridDim.x*blockDim.x)小于我希望处理的数组的大小时,通常的做法是创建一个循环并使线程网格移动通过整个阵列.在这种情况下,在处理一个循环迭代之后,每个线程必须移动到下一个未处理的位置,这是由gridDim.x*blockDim.x 有效的,整个网格线程跳过一维数据数组,一个网格宽度在时间.本博客文章进一步讨论了这个主题,有时称为"网格跨越循环" .
您可能需要考虑在NVIDIA网络研讨会页面上提供一些介绍性的CUDA网络研讨会.例如,这2:
如果你想更好地理解这些概念,那将花费2个小时.
这里详细介绍了网格跨越循环的一般主题.
alr*_*kai 46
从CUDA编程指南转述:
gridDim:此变量包含网格的尺寸.
blockIdx:此变量包含网格中的块索引.
blockDim:此变量包含块的尺寸.
threadIdx:此变量包含块内的线程索引.
你似乎对CUDA所具有的线程层次感到困惑; 简而言之,对于内核,将有1个网格(我总是可视化为3维立方体).它的每个元素都是一个块,这样声明的网格dim3 grid(10, 10, 2);总块数为10*10*2.反过来,每个块都是一个三维立方体线程.
话虽如此,通常只使用块和网格的x维度,这就像你的问题中的代码所做的那样.如果您正在使用1D阵列,这尤其重要.在这种情况下,您的tid+=blockDim.x * gridDim.x行实际上是网格中每个线程的唯一索引.这是因为你blockDim.x将是每个块的大小,你gridDim.x将是块的总数.
因此,如果您启动带参数的内核
dim3 block_dim(128,1,1);
dim3 grid_dim(10,1,1);
kernel<<<grid_dim,block_dim>>>(...);
Run Code Online (Sandbox Code Playgroud)
然后在你的内核中threadIdx.x + blockIdx.x*blockDim.x你有效地拥有:
threadIdx.x range from [0 ~ 128)
blockIdx.x range from [0 ~ 10)
blockDim.x equal to 128
gridDim.x equal to 10
因此,在计算中threadIdx.x + blockIdx.x*blockDim.x,您将拥有在以下定义的范围内的值:[0, 128) + 128 * [1, 10)这意味着您的tid值的范围为{0,1,2,...,1279}.当您想要将线程映射到任务时,这非常有用,因为这为您内核中的所有线程提供了唯一的标识符.
但是,如果你有
int tid = threadIdx.x + blockIdx.x * blockDim.x;
tid += blockDim.x * gridDim.x;
Run Code Online (Sandbox Code Playgroud)
然后你基本上有:tid = [0, 128) + 128 * [1, 10) + (128 * 10),你的tid值范围从{1280,1281,...,2559}我不确定那里的相关性,但这一切都取决于你的应用程序以及你如何映射你的线程你的数据.这种映射对于任何内核启动都是非常重要的,您就是决定如何完成它的人.当您启动内核时,您需要指定网格和块尺寸,并且您必须在内核中强制执行映射到数据.只要您不超过硬件限制(对于现代卡,每个块最多可以有2 ^ 10个线程,每个网格最多可以有2 ^ 16 - 1个块)