(5)cuda中的grid、block

文章目录

概要

在CUDA中,host和device 是两个重要的概念,我们用host指代CPU及其内存 ,而用device指代GPU及其内存

一般的CUDA程序的执行流程如下:

  1. 分配host内存,并进行数据初始化;
  2. 分配device内存,并从host将数据拷贝到device上;
  3. 调用CUDA的核函数在device上完成指定的运算;
  4. 将device上的运算结果拷贝到host上;
  5. 释放device和host上分配的内存。

整体架构流程

一般来说:

一个kernel对应一个grid

一个grid可以有多个block,一维~三维

一个block可以有多个thread,一维~三维

我们写的kernel function运行在block中的每个thread中。

https://cuda-programming.blogspot.com/2013/01/thread-and-block-heuristics-in-cuda.html

cpp 复制代码
#include <cuda_runtime.h>
#include <stdio.h>

//核函数 打印线程索引
__global__ void print_idx(){
    printf("block idx: (%3d, %3d, %3d), thread idx: (%3d, %3d, %3d)\n",
         blockIdx.z, blockIdx.y, blockIdx.x,
         threadIdx.z, threadIdx.y, threadIdx.x);
}

void demo_print(){
    int inputSize = 8;
    int blockDim = 4;  // block的维度 即 block中的线程数量
    int gridDim = inputSize / blockDim; // 计算出需要2个block,所以grid的维度为2

    dim3 block(blockDim);
    dim3 grid(gridDim);

    print_idx<<<grid, block>>>();
	//cudaDeviceSynchroize()来强制性的让kernel函数的结果执行结
	//束之后host再执行下一步。
    cudaDeviceSynchronize();
}

int main() {
    demo_print();
    return 0;
}

打印grid和block的维度

cpp 复制代码
__global__ void print_dim(){
    printf("grid dimension: (%3d, %3d, %3d), block dimension: (%3d, %3d, %3d)\n",
         gridDim.z, gridDim.y, gridDim.x,
         blockDim.z, blockDim.y, blockDim.x);
}

计算每个线程在block中的索引

cpp 复制代码
__global__ void print_thread_idx_per_block(){
    int index = threadIdx.z * blockDim.x * blockDim.y + \
              threadIdx.y * blockDim.x + \
              threadIdx.x;

    printf("block idx: (%3d, %3d, %3d), thread idx: %3d\n",
         blockIdx.z, blockIdx.y, blockIdx.x,
         index);
}

计算每个线程在grid中的索引

cpp 复制代码
__global__ void print_thread_idx_per_grid(){
    int block_Size  = blockDim.z * blockDim.y * blockDim.x;

    int block_Index = blockIdx.z * gridDim.x * gridDim.y + \
               blockIdx.y * gridDim.x + \
               blockIdx.x;

    int thread_Index = threadIdx.z * blockDim.x * blockDim.y + \
               threadIdx.y * blockDim.x + \
               threadIdx.x;

    int thread_index_in_grid  = block_Index * block_Size + thread_Index;

    printf("block idx: %3d, thread idx in block: %3d, thread index in grid: %3d\n", 
         block_Index, thread_Index, thread_index_in_grid);
}

完整代码与输出

cpp 复制代码
#include <cuda_runtime.h>
#include <iostream>
#include <stdio.h>

//核函数 打印线程索引
__global__ void print_idx(){
    printf("block idx: (%3d, %3d, %3d), thread idx: (%3d, %3d, %3d)\n",
         blockIdx.z, blockIdx.y, blockIdx.x,
         threadIdx.z, threadIdx.y, threadIdx.x);
}
//核函数 打印grid和block的维度
__global__ void print_dim(){
    printf("grid dimension: (%3d, %3d, %3d), block dimension: (%3d, %3d, %3d)\n",
         gridDim.z, gridDim.y, gridDim.x,
         blockDim.z, blockDim.y, blockDim.x);
}
//核函数 计算每个线程在block中的索引。GPU遍历顺序为Z,Y,X,所以计算的如下:
__global__ void print_thread_idx_per_block(){
    int index = threadIdx.z * blockDim.x * blockDim.y + \
              threadIdx.y * blockDim.x + \
              threadIdx.x;

    printf("block idx: (%3d, %3d, %3d), thread idx: %3d\n",
         blockIdx.z, blockIdx.y, blockIdx.x,
         index);
}

//核函数 计算每个线程在grid中的索引。GPU遍历顺序为Z,Y,X:
__global__ void print_thread_idx_per_grid(){
    int block_Size  = blockDim.z * blockDim.y * blockDim.x;

    int block_Index = blockIdx.z * gridDim.x * gridDim.y + \
               blockIdx.y * gridDim.x + \
               blockIdx.x;

    int thread_Index = threadIdx.z * blockDim.x * blockDim.y + \
               threadIdx.y * blockDim.x + \
               threadIdx.x;

    int thread_index_in_grid  = block_Index * block_Size + thread_Index;

    printf("block idx: %3d, thread idx in block: %3d, thread index in grid: %3d\n", 
         block_Index, thread_Index, thread_index_in_grid);
}



void demo_print(){
    int inputSize = 8;
    int blockDim = 4;  // block的维度 即 block中的线程数量
    int gridDim = inputSize / blockDim; // 计算出需要2个block,所以grid的维度为2

    dim3 block(blockDim);
    dim3 grid(gridDim);

    print_idx<<<grid, block>>>();
    //cudaDeviceSynchroize()来强制性的让kernel函数的结果执行结
	//束之后host再执行下一步。
    cudaDeviceSynchronize();
    std::cout << "---------------分割线---------------------------" << std::endl;
    print_dim<<<grid, block>>>();
    cudaDeviceSynchronize();
    std::cout << "---------------分割线---------------------------" << std::endl;
    print_thread_idx_per_block<<<grid, block>>>();
    cudaDeviceSynchronize();
    std::cout << "---------------分割线---------------------------" << std::endl;
    print_thread_idx_per_grid<<<grid, block>>>();
    cudaDeviceSynchronize();

}

int main() {
    demo_print();
    return 0;
}
bash 复制代码
cmake_minimum_required(VERSION 3.10)

project(test CUDA)
set(CMAKE_CUDA_STANDARD 20)

add_executable(test1 print_index_demo1.cu)
相关推荐
Lucis__1 分钟前
基于责任链模式的消息队列—异步处理流水线的最佳实践
linux·c++·消息队列·责任链模式·ipc
Jackson_GJH1 小时前
C++虚函数、虚继承、虚基类
c++·c++基础
码匠许师傅1 小时前
【C++三方组件】开篇总论:为什么需要以及如何选型?
开发语言·c++
h_a_o777oah1 小时前
【Games101】C++ 软光追:光线追踪的求交逻辑和 BVH 提效实现及代码实现细节
c++·计算机图形学·光线追踪·games101·bvh·求交算法·软件渲染
cvby1 小时前
C++11--右值引用和移动语义
开发语言·c++
xiangyun612 小时前
【408数据结构 03】线性表与顺序表:C++手写SeqList
开发语言·数据结构·c++
xxxiugou1233 小时前
双指针解题秘籍:从入门到精通
c语言·数据结构·c++·算法
代码中介商3 小时前
C++ 预约系统实战(一):项目总览与 C/S 架构设计
c语言·开发语言·c++
云边有个稻草人4 小时前
Tera Term 鸿蒙 PC 适配全记录:用 ArkUI 与 Native C++ 重建多协议终端工作流
c++·stm32·harmonyos
牛油果子哥q4 小时前
多模态大模型工程入门:图文Embedding、图文RAG、图片解析、C++多模态接口封装实战
开发语言·c++·embedding