欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 美景 > [CUDA编程] --- cuda线程模型

[CUDA编程] --- cuda线程模型

2025/7/8 23:32:43 来源:https://blog.csdn.net/weixin_42445727/article/details/140890426  浏览:    关键词:[CUDA编程] --- cuda线程模型

1 核函数

先看一个cuda版本的hello world

#include <stdio.h>__global__ void helloworld()
{printf("hello world\n");
}int main()
{helloworld()<<<1, 1>>>();cudaDeviceSynchronize();return 0;
}

这里helloworld()<<<1, 1>>>();就是核函数,关于核函数:

1 核函数(kernel function)在CPU调用,GPU执行
2 核函数必须用__global__修饰,返回值必须是void
3 核函数有两种写法,__global__ void xxx()或者 void __global__ xxx()
4 核函数的几个限制4.1 核函数只能访问GPU内存4.2 核函数不能使用变长参数4.3 核函数不能使用static变量4.4 核函数不能使用函数指针4.5 核函数具有异步性

helloworld()<<<1, 1>>>();这行代码是什么意思,我们还不知道,不着急,接着往下看。

2 线程管理

当内核函数开始执行,如何组织GPU的线程就变成了最主要的问题了,我们必须明确,一个核函数只能有一个grid,一个grid可以有很多个块,每个块可以有很多的线程,这种分层的组织结构使得我们的并行过程更加自如灵活:
在这里插入图片描述
一个线程块block中的线程可以完成下述协作:

  • 同步
  • 共享内存

不同块内线程不能相互影响!他们是物理隔离的!

3 线程索引计算方式

3.1 内建变量gridDim / blockDim / blockIdx / threadIdx

内建变量只在核函数有限,且无需定义。
threadIdx是一个uint3类型,表示一个线程的索引。
blockIdx是一个uint3类型,表示一个线程块的索引,一个线程块中通常有多个线程。
blockDim是一个dim3类型,表示线程块的大小。
gridDim是一个dim3类型,表示网格的大小,一个网格中通常有多个线程块。

gridDim和blockDim

gridDim和blockDim是dim3类型(基于uint3定义的数据结构)的变量,都包含三个字段x,y,z,这两个内建变量三个字段的值分别等于初始化时grid_size和block_size的值。如:

dim3 grid_size(2,1,1);
dim3 block_size(3,2,1);
kernel_xxx<<<<gird_size, block_size>>>();/*
gridDim.x=2,  gridDim.y=1,  gridDim.z=1
blockDim.x=3, blockDim.y=2, blockDim.z=1
*/

Note: gridDim和blockDim没有指定的维度默认为1

blockIdx和threadIdx

blockIdx和threadIdx是类型为uint3的变量,该类型是一个结构体,包含x,y,z三个字段,其取值范围如下:
blockIdx.x 取值范围[0, gridDim.x -1]
blockIdx.y 取值范围[0, gridDim.y -1]
blockIdx.z 取值范围[0, gridDim.y -1]
threadIdx.x 取值范围[0, blockDim.x -1]
threadIdx.y 取值范围[0, blockDim.y -1]
threadIdx.z 取值范围[0, blockDim.z -1]

3.2 线程索引计算方式

一个Grid可以包含多个Blocks,Blocks的组织方式可以是一维的,二维或者三维的。block包含多个Threads,这些Threads的组织方式也可以是一维,二维或者三维的。所以共有九种方式。
CUDA中每一个线程都有一个唯一的标识ID—ThreadIdx,这个ID随着Grid和Block的划分方式的不同而变化,这里给出Grid和Block不同划分方式下线程索引ID的计算公式。

在这里插入图片描述
第一种:一维grid,一维block

int threadId = blockIdx.x *blockDim.x + threadIdx.x;  

第二种:一维grid,二维block

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

第三种:一维grid,三维block

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

第四种:二维grid,一维block

int blockId = blockIdx.y * gridDim.x + blockIdx.x;  int threadId = blockId * blockDim.x + threadIdx.x; 

第五种:二维grid,二维block

int blockId = blockIdx.x + blockIdx.y * gridDim.x;  int threadId = blockId * (blockDim.x * blockDim.y)  

第六种:二维grid,三维block

 int blockId = blockIdx.x + blockIdx.y * gridDim.x;  int threadId = blockId * (blockDim.x * blockDim.y * blockDim.z)  + (threadIdx.z * (blockDim.x * blockDim.y))  + (threadIdx.y * blockDim.x) + threadIdx.x; 

第七种:三维grid,一维block

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

第八种:三维grid,二维block

 int blockId = blockIdx.x + blockIdx.y * gridDim.x  + gridDim.x * gridDim.y * blockIdx.z;  int threadId = blockId * (blockDim.x * blockDim.y)  + (threadIdx.y * blockDim.x) + threadIdx.x;  

第九种:三维grid,三维block

 int blockId = blockIdx.x + blockIdx.y * gridDim.x  + gridDim.x * gridDim.y * blockIdx.z;  int threadId = blockId * (blockDim.x * blockDim.y * blockDim.z)  + (threadIdx.z * (blockDim.x * blockDim.y))  + (threadIdx.y * blockDim.x) + threadIdx.x;   

3.3 网格大小限制

gridDim.x  最大值 2^31-1
gridDim.y  最大值 2^16-1
gridDim.z  最大值 2^16-1blockDim.x  最大值 1024
blockDim.y  最大值 1024
blockDim.z  最大值 64

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词