cuda - CUDA线程和块组织方向
问题描述
在 CUDA 编程中,线程和块有多个方向(x、y 和 z)。
到目前为止,我忽略了这一点,只考虑了 x 方向(threadIdx.x、blockIdx.x、blockDim.x 等)。
显然,块内的线程和网格上的块都排列为立方体。但是,如果是这种情况,为什么指定 x 方向就足够了?我不会像那样处理多个线程吗?仅使用 x 方向,我是否能够处理我的 GPU 可用的所有线程?
解决方案
仅使用 x 方向,我是否能够处理我的 GPU 可用的所有线程?
如果我们谈论的是启动约 2 万亿或更少线程的愿望,那么就没有特别要求使用多维块或网格。所有具有 3.0 及更高计算能力的 CUDA GPU 都可以使用一维网格组织启动多达约 20 亿个块 (2^31-1),每个块有 1024 个线程。
使用网格步长循环之类的方法,对我来说似乎很少需要超过 2 万亿个线程。
我在没有正式证据的情况下声称可以在 1D 网格中实现的任何问题都可以在 2D 或 3D 网格中实现,反之亦然。这只是从一种实现到另一种实现的数学映射。此外,应该可以在任一实现中安排重要的副产品,例如合并访问。
当以 1D 或多维方式实现时,可能会有一些可读性优势、代码复杂性优势以及可能的较小性能考虑。我能想到的通常情况是要处理的数据“固有地”是多维的。在这种情况下,让 CUDA 引擎为您生成 2 或 3 个不同的索引:
int idx = threadIdx.x+blockDim.x*blockIdx.x;
int idy = threadIdx.y+blockDim.y*blockIdx.y;
可能比使用 1D 网格索引并从这些索引计算 2D 数据索引更简单:
int tid = threadIdx.x+blockDim.x*blockIdx.x;
int idx = tid%DATA_WIDTH;
int idy = tid/DATA_WIDTH;
(上面的整数除法运算在一般情况下是不可避免的。模运算可以使用整数除法的结果来简化。)
可以说,当只创建一维网格时,到达同一点需要额外的代码行和额外的除法运算。但是,我建议即使这是小菜一碟,作为程序员,您应该使用对您来说最合理和最舒适的方法。
如果出于某种原因您希望启动超过 2 万亿个线程,那么至少移动到多维网格是不可避免的。
显然,块内的线程和网格上的块都排列为立方体。
要了解在任何情况下如何计算线程块线程索引,请参阅编程指南。很明显,一种情况可以等同于另一种情况——无论您如何指定线程块尺寸,每个线程都会获得一个唯一的线程 ID。在我看来,如果您以这种方式指定配置,则只能将线程块视为线程的“立方体”(即 3 维):
dim3 block(32,8,4); //for example
但是,如果是这种情况,为什么指定 x 方向就足够了?我不会像那样处理多个线程吗?
如果在 32,8,4 的情况下只使用单个线程块维度创建线程索引:
int tid = threadIdx.x;
那么您肯定会使用该方法“处理”多个线程(在 y 和 z 中)。根据我的经验,这通常是“损坏”的代码。因此,如果将块或网格指定为一维,则设计为使用多维块或网格的内核可能无法正常工作,并且相反的陈述也是正确的。cuda
您可以在标签上找到此类问题的示例(线程索引计算对于网格设计不正确) 。
推荐阅读
- sql - 一种更有效的方式来组织数据库模式以在相关表中存储键值
- node.js - 是否有任何节点库可以创建类似于文件流的内存流?
- couchdb - Google chrome 84.0 在 Ubuntu 18.04 上不显示 HTTP Auth 弹出对话框
- asp.net-core - 如何在 .Net Core 3.1 中的 OpenId 连接时禁用 ssl 证书验证?
- regex - 获取国家同义词但不获取标志符号的 Wikidata 查询
- html - 如何使用 CSS 使文本始终位于页面底部
- python - 辛普森在 Python 中的积分规则
- c++ - C++ 本地地图在范围之外使用并且仍然有效
- navigation - Java中具有多个顶级目的地的导航图
- javascript - 具有相同键的数组的Javascript连接值