CUDA 编程中的 <<<...>>> 语法。
核心概念
在 CUDA 编程中,<<<...>>> 不是一个函数,而是一个称为执行配置的语法符号。它的唯一作用是用来指定如何在 GPU 上启动一个核函数。
简单来说,当你写:
cpp
my_kernel<<<grid_size, block_size, shared_memory_size, stream>>>(arguments...);
你是在告诉 CUDA 运行时:
“请启动一个名为 my_kernel 的核函数,并按照我指定的方式(<<<...>>> 里的参数)在 GPU 上组织大量的线程来执行它。”
<<<...>>> 内的参数详解
<<<...>>> 最多可以接受四个参数,但最常用的是前两个:
-
Grid Size(网格大小)
-
含义: 定义了一个网格中包含多少个线程块。
-
类型: 可以是
int或dim3类型。 -
示例:
-
<<<10, ...>>>表示启动一个由 10 个线程块组成的一维网格。 -
<<<dim3(2, 3, 1), ...>>>表示启动一个 2x3x1 的二维网格,共 6 个线程块。
-
-
-
Block Size(块大小)
-
含义: 定义了每个线程块中包含多少个线程。
-
类型: 可以是
int或dim3类型。 -
限制: 每个线程块的线程数是有上限的(例如,现代 GPU 通常是 1024)。
-
示例:
-
<<<..., 256>>>表示每个线程块包含 256 个线程,组织成一维。 -
<<<..., dim3(16, 16)>>>表示每个线程块包含 16x16=256 个线程,组织成二维。
-
-
-
Shared Memory Size(共享内存大小,可选)
-
含义: 为每个线程块动态分配的共享内存大小(以字节为单位)。如果不需要动态分配,可以省略或设为 0。
-
类型:
size_t -
示例:
<<<10, 256, 2048>>>表示每个线程块额外分配 2048 字节的共享内存。
-
-
Stream(流,可选)
-
含义: 指定核函数在哪个流中执行。用于实现核函数执行的并发。如果省略,则在默认流(流 0)中执行。
-
类型:
cudaStream_t -
示例:
<<<10, 256, 0, my_stream>>>
-
线程层次结构:为什么需要 <<<...>>>
CUDA 的核心思想是大规模并行。为了管理和组织成千上万个线程,CUDA 使用了一个两层层次模型:
-
网格: 最高级别的组织单位。一个网格包含多个线程块。
-
线程块: 网格中的基本单位。一个线程块包含多个线程。
<<<grid_size, block_size>>> 正是用来定义这个层次结构的:
-
总线程数 = grid_size * block_size
-
例如
<<<100, 256>>>意味着启动了100 * 256 = 25,600个线程。
在核函数内部,你可以通过内置变量来唯一标识每个线程,从而让每个线程处理不同的数据:
-
blockIdx.x,blockIdx.y,blockIdx.z: 当前线程块在网格中的索引。 -
threadIdx.x,threadIdx.y,threadIdx.z: 当前线程在线程块中的索引。
示例:数组相加
cpp
// 核函数:每个线程负责计算一个元素的和
__global__ void addKernel(int *a, int *b, int *c, int n) {
// 计算当前线程的全局索引
int index = blockIdx.x * blockDim.x + threadIdx.x;
// 确保索引不会越界
if (index < n) {
c[index] = a[index] + b[index];
}
}
int main() {
// ... 分配内存、初始化数据等操作 ...
// 启动核函数
int blockSize = 256; // 每个块256个线程
int gridSize = (n + blockSize - 1) / blockSize; // 计算需要多少个块才能覆盖n个元素
// 使用<<<gridSize, blockSize>>>来启动核函数
addKernel<<<gridSize, blockSize>>>(dev_a, dev_b, dev_c, n);
// ... 将结果拷贝回主机等其他操作 ...
}
在这个例子中,gridSize 被计算为 (n + 255) / 256,以确保有足够多的线程(>= n)来处理所有 n 个数组元素。
总结
| 特性 | 描述 |
|---|---|
| 名称 | 执行配置语法 |
| 作用 | 指定如何组织线程层次(网格和线程块)以在 GPU 上启动核函数。 |
| 核心参数 | <<<网格大小,线程块大小>>> |
| 可选参数 | 共享内存大小、CUDA 流。 |
| 类比 | 就像在命令一支军队:网格是整个军队,线程块是师或团,线程是士兵。<<<...>>> 就是你下达的指令:“派出 10 个师(网格),每个师 256 人(线程块)。” |
简单来说,<<<...>>> 是连接主机(CPU)代码和设备(GPU)核函数的桥梁,是启动大规模并行计算的钥匙。
7418

被折叠的 条评论
为什么被折叠?



