【问题标题】:How to calculate individual thread coordinate indices in 3 D grids?如何计算 3D 网格中的单个线程坐标索引?
【发布时间】:2013-07-19 16:52:04
【问题描述】:

我有一个由 3D 块组成的 3D 网格。我希望每次调用内核时计算每个坐标的各个线程索引。我有这些参数:

dim3 blocks_query(32,32,32);
dim3 threads_query(32,32,32);
kernel<<< blocks_query,threads_query >>>();

在内核内部,我希望计算 x,y 和 z 坐标的各个值,例如 x=0,y=0,z=0, x=0,y=0,z=1, x= 0,y=0,z=2,....提前谢谢....

【问题讨论】:

    标签: cuda


    【解决方案1】:

    单个线程索引(x、y、z 坐标)可以在内核内部计算如下:

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

    请记住,每个块的线程数受 GPU 限制。所以你创建的块大小是无效的。

    dim3 threads_query(32,32,32)
    

    它等于每个块 32768 个线程,当前任何 CUDA 设备都不支持。目前,计算能力 2.0 及以上的 GPU 支持每个块最多 1024 个线程,而旧 GPU 最多支持 512 个线程。您应该减小块大小,否则内核将无法启动。 另一件需要注意的是,您正在创建 3D 网格,该网格仅在 Compute 2.0 及更高版本的 CUDA GPU 上受支持。

    更新

    假设你的3D数据的维度是xDimyDimzDim,那么一个通用的线程块网格可以形成如下:

    dim3 threads_query(8,8,8);
    
    dim3 blocks_query;
    
    blocks_query.x = (xDim + threads_query.x - 1)/threads_query.x;
    blocks_query.y = (yDim + threads_query.y - 1)/threads_query.y;
    blocks_query.z = (zDim + threads_query.z - 1)/threads_query.z;
    

    上述方法将创建等于或大于总数据大小的线程总数。额外的线程可能会导致无效的内存访问。所以在内核内部执行绑定检查。您可以通过传递xDimyDimzDim 作为内核参数并在内核中添加以下行来做到这一点:

    if(x>=xDim || y>=yDim || z>=zDim) return;
    

    【讨论】:

    • 非常感谢 :) 我只是有一个疑问,如果我将这些 x、y、z 值组合并使用它们,它们的含义是否与第 (0,0,0) 个线程相同,(0第 ,0,1) 个线程,第 (0,0,2) 个线程等等?
    • 是的,意思是一样的。这些是全局线程索引。
    • 非常感谢 :) 关于线程,我应该如何设计可变线程和块?我的问题是我需要在 x、y 和 z 方向处理任意数量的点(仅在运行时知道)。
    猜你喜欢
    • 2012-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-30
    • 2022-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多