【cuda编程】CUDA的运行方式以及grid、block结构关系

news/2024/5/9 0:26:58/文章来源:https://blog.csdn.net/QLeelq/article/details/127284410

文章目录

  • 1. CUDA基础知识
    • 1.1 程序基本运行顺序
    • 1.2 grid与block
    • 1.3 dim类型定义
  • 2. CUDA的第一个程序
  • 3. CUDA线程的组织结构——grid与block关系

1. CUDA基础知识

1.1 程序基本运行顺序

一般来说,一个cpu+gpu的程序运行如下所示:

在这里插入图片描述

1.2 grid与block

从GPU至线程的关系依次为:显卡(GPU)->网格(grid)->线程块(block)->线程(thread) 。从网格开始最大为3维,当然也可以1维了。

  • 网格(grid):一个内核函数(kernel)就是一个网格,里面所有线程都在这个网格范围内,里面的线程共享全局内存空间
  • 线程块(block):一个网格可以包含很多个block,block之间可以通过“同步”和“共享内存”进行协作,block之间的区分通过“blockIdx”
  • 线程(thread):一个线程块可以包含很多个thread,thread之间区分通过threadIdx,当然如果block不一样,threadIdx肯定需要继续区分
  • blockIdx/threadIdx:是dim3类型变量(整型),是索引线程的关键,对某个线程的索引:blockIdx.x/y/z,threadIdx.x/y/z
  • gridDim/blockDim:也是dim3类型变量,是检查线程维数的关键,对某个线程所属的网格维数、线程块维数进行检测:gridDim.x/y/z,blockDim.x/y/z

1.3 dim类型定义

//定义参考
dim3 dd;//dd.x,dd.y,dd.z 默认为1
dim3 dd(2,3);//dd.x==2,dd.y==3,dd.z==1//一般定义如下
dim3 grid(2,3);//就是定义一个网格,里面包含2*3*1个block
dim3 block(4,5);//就是定义一个线程块,里面包含4*5*1个thread

2. CUDA的第一个程序

下面程序是一个简单的GPU调用程序,注意一下几点:

  • BASE_CUDA_CHECK:为CUDA操作的验证,加上之后可以很方便的知道自己的程序在哪一行出错了。
  • helloFromGPU:为在GPU中执行的程序。
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>
#include <iostream>#define BASE_CUDA_CHECK(condition) { GPUAssert((condition), __FILE__, __LINE__); }inline void GPUAssert(cudaError_t code, const char *file, int line, bool abort = true) {if (code != cudaSuccess) {fprintf(stderr, "GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line);if (abort) {exit(code);}}
}__global__ void helloFromGPU()
{printf("Hello World from GPU!\n");
}int main(int argc, char **argv)
{//CPU端的打印输出std::cout<<"Hello World from CPU!"<<std::endl;// CUDA调用helloFromGPU<<<1, 10>>>();//CPU端的打印输出std::cout<<"Hello World from CPU!"<<std::endl;BASE_CUDA_CHECK(cudaDeviceReset());return 0;
}

从输出可以看出,进入GPU后,CPU并不会等待GPU结束,而是CPU程序继续往下执行

在这里插入图片描述

3. CUDA线程的组织结构——grid与block关系

CUDA使用多级索引的方式访问线程。

  • 定位Block:第一级索引是(grid.xIdx, grid.yIdy),通过它我们就能找到了这个线程块的位置。
  • 定位thread:第二级索引(block.xIdx, block.yIdx, block.zIdx)来定位到指定的线程。

grid和block都是定义为dim3类型的变量,dim3可以看成是包含三个无符号整数(x,y,z)成员的结构体变量,在定义时,缺省值初始化为1。因此grid和block可以灵活地定义为1-dim,2-dim以及3-dim结构,对于图中结构(水平方向为x轴),定义的grid和block如下所示

dim3 grid(3, 2);
dim3 block(5, 3);
kernel_fun<<< grid, block >>>(prams...);

定义图解如下:
在这里插入图片描述

CUDA中每一个线程都有一个唯一的标识ID—ThreadIdx,这个ID随着Grid和Block的划分方式的不同而变化,这里给出Grid和Block不同划分方式下线程索引ID的计算公式。

  1. grid划分成1维,block划分为1维
    int threadId = blockIdx.x *blockDim.x + threadIdx.x;  
  1. grid划分成1维,block划分为2维
int threadId = blockIdx.x * blockDim.x * blockDim.y+ threadIdx.y * blockDim.x + threadIdx.x;  
  1. 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;  
  1. grid划分成2维,block划分为1维
    int blockId = blockIdx.y * gridDim.x + blockIdx.x;  int threadId = blockId * blockDim.x + threadIdx.x;  
  1. 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;  
  1. 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;  
  1. 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;  
  1. 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;  
  1. 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;     

下面的程序是认识grid和block很好的程序,可以自己尝试改变参数调节。

#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>
#include <iostream>#define BASE_CUDA_CHECK(condition) { GPUAssert((condition), __FILE__, __LINE__); }inline void GPUAssert(cudaError_t code, const char *file, int line, bool abort = true) {if (code != cudaSuccess) {fprintf(stderr, "GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line);if (abort) {exit(code);}}
}__global__ void checkIndex(void)
{printf("threadIdx:(%d, %d, %d)\n", threadIdx.x, threadIdx.y, threadIdx.z);printf("blockIdx:(%d, %d, %d)\n", blockIdx.x, blockIdx.y, blockIdx.z);printf("blockDim:(%d, %d, %d)\n", blockDim.x, blockDim.y, blockDim.z);printf("gridDim:(%d, %d, %d)\n", gridDim.x, gridDim.y, gridDim.z);
}int main(int argc, char **argv)
{int nElem = 6;//定义总计算量dim3 block(3);// 定义grid和blockdim3 grid((nElem + block.x - 1) / block.x);// 定义grid和blockprintf("grid.x %d grid.y %d grid.z %d\n", grid.x, grid.y, grid.z);// CPU端检测维度printf("block.x %d block.y %d block.z %d\n", block.x, block.y, block.z);checkIndex<<<grid, block>>>();// GPU端检测维度BASE_CUDA_CHECK(cudaDeviceReset());// 恢复GPUreturn 0;
}

输出如下,因为GPU之间是并行执行的,所以它们的输出顺序也是不固定的

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_218670.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络原理——No.4 传输层_TCP协议中的延迟应答, 捎带应答, 面向字节流与TCP的异常处理

JavaEE传送门JavaEE 网络原理——No.2 传输层_TCP的连接管理 网络原理——No.3 传输层_TCP的滑动窗口, 流量控制与拥塞控制 目录延迟应答捎带应答面向字节流粘包问题TCP 中的异常处理(连接异常)TCP 和 UDP 的应用场景延迟应答 一种提高传输效率的机制, 又是基于流量控制, 来引…

调度线程池ScheduledThreadPoolExecutor源码解析

实现机制分析 我们先思考下&#xff0c;如果让大家去实现ScheduledThreadPoolExecutor可以周期性执行任务的功能&#xff0c;需要考虑哪些方面呢&#xff1f; ScheduledThreadPoolExecutor的整体实现思路是什么呢&#xff1f; 答&#xff1a; 我们是不是可以继承线程池类&am…

docker快速安装redis

一.背景 开发环境中&#xff0c;经常需要redis本地环境&#xff0c;方便开发。准备在本机的虚拟机里面准备一个redis环境。 二.版本信息 操作系统&#xff1a;Windows 10 家庭版 Oracle VM VirtualBox&#xff1a;版本 6.0.10 r132072 (Qt5.6.2) Ubuntu:16.04.6-desktop-a…

STM32CubeMX学习笔记(44)——USB接口使用(HID按键)

一、USB简介 USB&#xff08;Universal Serial BUS&#xff09;通用串行总线&#xff0c;是一个外部总线标准&#xff0c;用于规范电脑与外部设备的连接和通讯。是应用在 PC 领域的接口技术。USB 接口支持设备的即插即用和热插拔功能。USB 是在 1994 年底由英特尔、康柏、IBM、…

淘宝十年技术思考与总结,让人惊叹的进化脱变,最终确认版已发布

看了淘宝在将近10年时间里技术的革新&#xff0c;我对技术与业务有了更近一步的认识。 任何技术都是从小做起&#xff0c;一步步做起来的。如果你让04年的淘宝去做一个能承受10亿次访问的网站&#xff0c;马云那时候肯定会伤透脑筋&#xff0c;即使做半年都做不出来。但现在&a…

Java实现邮件发送

这里我们以QQ邮箱为例。 一、导入依赖:<dependencies><!-- https://mvnrepository.com/artifact/javax.activation/activation --><dependency><groupId>javax.activation</groupId><artifactId>activation</artifactId><versio…

联邦学习:联邦异构知识图谱划分

在联邦场景下,C个知识图谱位于不同的客户端上。知识图谱拥的实体集合之间可能会存在重叠,而其关系集合和元组集合之间则不会重叠。我们联系一下现实场景看这是合理的,比如在不同客户端对应不同银行的情况下,由于不同银行都有着自己的业务流程,所以关系集合不重叠。本文我们…

如何给PDF文件添加水印?PDF免费添加水印教程来了

有时候&#xff0c;为了不让别人盗用我们PDF文件里面的内容或图片&#xff0c;或者是出于宣传产品的目的&#xff0c;我们经常会需要给自己的PDF文件添加各种类型的水印&#xff0c;那你们知道如何给PDF文件添加水印吗&#xff1f;下面我们就来看看如何给PDF文件添加水印&#…

瞄准五金行业采购痛难点,智慧采购管理系统实现业务流程数据化,提高采购效率

五金行业采购一直是传统企业采购的软肋和头痛环节&#xff0c;无论从人力成本&#xff0c;物料成本&#xff0c;财务监管成本&#xff0c;物流成本等都存在一个整合服务需求&#xff0c;同时&#xff0c;传统五金行业采购难的问题&#xff0c;也一直制约着行业发展&#xff0c;…

股指期货高手陈(股指期货第一人)

​ 什么是股指期货&#xff0c;怎么玩&#xff1f;请教高手&#xff01; 股指期货&#xff08;Stock Index Futures&#xff0c;即股票价格指数期货&#xff0c;也可称为股价指数期货&#xff09;&#xff0c;是指以股价指数为标的资产的标准化期货合约。双方约定在未来某个特…

RK3399应用开发 | 移植libdrm到rk3399开发板(2.4.113)

一、下载源码 下载地址:https://dri.freedesktop.org/libdrm/。 这里我下载最新的2.4.113版本: wget https://dri.freedesktop.org/libdrm/libdrm-2.4.113.tar.xz解压: xz -d libdrm-2.4.113.tar.xz tar -xf libdrm-2.4.113.tar二、编译环境安装 1. 更新python ubuntu安…

【安信可NB-IoT模组EC系列应用笔记⑧】用NB-IoT模组EC系列了解LwM2M协议并接入云平台

文章目录前言一、测试准备1、硬件准备2、云平台准备二、云平台连接1.注册入网2.读取IMSI及IMEI3.利用IMSI及IMEI创建设备4.LwM2M连接云平台设备三、 数据互交1.ATMIPLNOTIFY 通知属性变化2.ATMIPLREADRSP 返回读取结果3.ATMIPLWRITERSP 发送写入结果4.ATMIPLEXECUTERSP 发送执行…

半乳糖-人血清白蛋白 Gal-HSA,Gal-PEG-HSA 半乳糖修饰人血清白蛋白

产品名称&#xff1a;半乳糖修饰人血清白蛋白 Gal-HSA 用途&#xff1a;科研 状态&#xff1a;固体/粉末/溶液 产品规格&#xff1a;1g/5g/10g 保存&#xff1a;冷藏 储藏条件&#xff1a;-20℃ 储存时间&#xff1a;1年 温馨提醒&#xff1a;仅供科研&#xff0c;不能用于人体…

supervisor管理prometheus进程

一、supervisor简单介绍 二、supervisor安装 三、supervisor部署应用 四、supervisorctl常用指令 五、supervisor测试 一、supervisor简单介绍 1、 概述 supervisor是一个Python编写的进程管理工具&#xff0c;可以方便启动、重启、关闭、单个或多个进程&#xff0c;可以简…

中国数字视听行业全景调研与投资趋势预测报告

数字视听和视听技术的概念 传统视听技术既包括视觉技术&#xff0c;也包括听觉技术&#xff0c;即模拟信号&#xff0c;包括录音录像、摄影等。随着时代和科技的发展&#xff0c;先进的计算机技术在检察系统和办公业务中得到广泛应用&#xff0c;传统的视听技术也逐渐向数字化方…

硬件开发趋势与技术探索

LiveVideoStackCon 2022 音视频技术大会 北京站将于11月25日至26日在北京丽亭华苑酒店召开&#xff0c;本次大会将延续【音视频无限可能】的主题&#xff0c;邀请业内众多企业及专家学者&#xff0c;将他们在过去一年乃至更长时间里对音视频在更多领域和场景下应用的探索、在实…

CSS3 1 CSS3 响应式布局 1.3 Grid 布局

CSS3 文章目录CSS31 CSS3 响应式布局1.3 Grid 布局1.3.1 Grid 布局简介1.3.2 开启grid 布局1.3.3 排列元素1.3.4 对齐方式1 CSS3 响应式布局 1.3 Grid 布局 【【迄今为止最易懂】2分钟掌握 CSS Grid 布局】 https://www.bilibili.com/video/BV18p411A7JB?share_sourcecopy_w…

YOLOv5、v7改进之三十八:引入RepVGG模型结构

前 言&#xff1a;作为当前先进的深度学习目标检测算法YOLOv7&#xff0c;已经集合了大量的trick&#xff0c;但是还是有提高和改进的空间&#xff0c;针对具体应用场景下的检测难点&#xff0c;可以不同的改进方法。此后的系列文章&#xff0c;将重点对YOLOv7的如何改进进行详…

【微服务】微服务万字实战,带你了解工程原理

微服务实战1、前期准备1.1 技术选型1.2 模块设计1.3 微服务调用2、创建父工程3、创建基础模块3.1 导入依赖3.2 创建实体类4、创建用户微服务4.1 创建shop-user模块4.2 用户微服务启动类4.3 创建配置文件5、创建商品微服务5.1 创建shop_product模块5.2 商品微服务启动类5.3 创建…

【自学CSS笔记第7篇】——CSS三大特征(这一篇就够了)

其实&#xff0c;我清楚的知道什么是对的什么是错的&#xff0c;什么该做什么不该做&#xff0c;然而懒惰的天性驱使我们每每做出错误的决定&#xff0c;结束后我又再一次重复着厌倦和懊恼。 目录 CSS的三大特性总览: 层叠性&#xff1a; 继承性&#xff1a; 优先级&#x…