CUDA软件架构—网格(Grid)、线程块(Block)和线程(Thread)的组织关系以及线程索引的计算公式...

本文介绍CUDA编程中网格(Grid)、线程块(Block)和线程(Thread)的概念及其组织关系,包括最大数量限制和线程索引计算公式。

网格(Grid)、线程块(Block)和线程(Thread)的组织关系


CUDA的软件架构由网格(Grid)、线程块(Block)和线程(Thread)组成,相当于把GPU上的计算单元分为若干(2~3)个网格,每个网格内包含若干(65535)个线程块,每个线程块包含若干(512)个线程,三者的关系如下图:


Thread,block,grid是CUDA编程上的概念,为了方便程序员软件设计,组织线程。

  • thread:一个CUDA的并行程序会被以许多个threads来执行。
  • block:数个threads会被群组成一个block,同一个block中的threads可以同步,也可以通过shared memory通信。
  • grid:多个blocks则会再构成grid。

网格(Grid)、线程块(Block)和线程(Thread)的最大数量


CUDA中可以创建的网格数量跟GPU的计算能力有关,可创建的Grid、Block和Thread的最大数量参看以下表格:



在单一维度上,程序的执行可以由多达3*65535*512=100661760(一亿)个线程并行执行,这对在CPU上创建并行线程来说是不可想象的。

线程索引的计算公式


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

1、 grid划分成1维,block划分为1维

    int threadId = blockIdx.x *blockDim.x + threadIdx.x;  
    
  
2、 grid划分成1维,block划分为2维  

    int threadId = blockIdx.x * blockDim.x * blockDim.y+ threadIdx.y * blockDim.x + threadIdx.x;  
  
  
3、 grid划分成1维,block划分为3维  

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

  
4、 grid划分成2维,block划分为1维  

    int blockId = blockIdx.y * gridDim.x + blockIdx.x;  
    int threadId = blockId * blockDim.x + threadIdx.x;  
   
  
5、 grid划分成2维,block划分为2维 

    int blockId = blockIdx.x + blockIdx.y * gridDim.x;  
    int threadId = blockId * (blockDim.x * blockDim.y)  
                       + (threadIdx.y * blockDim.x) + threadIdx.x;  
    
  
6、 grid划分成2维,block划分为3维

    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;  
   
  
7、 grid划分成3维,block划分为1维 

    int blockId = blockIdx.x + blockIdx.y * gridDim.x  
                     + gridDim.x * gridDim.y * blockIdx.z;  
    int threadId = blockId * blockDim.x + threadIdx.x;  
   
  
8、 grid划分成3维,block划分为2维  

    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;  
   
  
9、 grid划分成3维,block划分为3维

    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;     


转载于:https://www.cnblogs.com/mtcnn/p/9411871.html

### CUDA网格线程索引的概念 #### 线程 (Thread)CUDA编程模型中,最小的执行单元是线程。每个线程可以独立执行相同的指令流,但处理不同的数据片段。线程通过`threadIdx.x`, `threadIdx.y`, `threadIdx.z` 来唯一标识其位置[^1]。 #### 线程 (Block) 多个线程被组织成一个线程block)。同一内的线程能够协作完成更复杂的任务,并且可以在硬件上共享资源如寄存器文件本地内存。线程同样具有三维结构,由`blockIdx.x`, `blockIdx.y`, `blockIdx.z` 定义其坐标。 #### 网格 (Grid) 若干个线程进一步组成一个更大的集合称为网格(grid)。整个GPU上的所有活动都发生在这样的二维或一维数组形式存在的网格内。对于大多数应用来说,定义好合适的网格尺寸是非常重要的,因为这决定了有多少组线程会被启动去解决问题的一部分。 ### 使用方法与示例 为了更好地理解如何利用上述组件编写有效的CUDA程序,下面给出一段简单的C++代码作为示范: ```cpp __global__ void vectorAdd(const float* A, const float* B, float* C, int numElements) { // 计算全局线程ID int i = blockIdx.x * blockDim.x + threadIdx.x; if(i < numElements){ C[i] = A[i] + B[i]; } } ``` 在此函数中: - `blockDim.x`: 表示当前线程所属的线程中的线程数量; - `blockIdx.x`: 当前线程所在的线程在整个网格中的编号; - `threadIdx.x`: 当前正在运行的具体线程在其所在线程里的相对位置; 这段代码展示了怎样基于这些参数来分配工作任务给各个线程,从而实现向量加法操作[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值