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

news2024/11/10 13:02:18

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-1

blockDim.x  最大值 1024
blockDim.y  最大值 1024
blockDim.z  最大值 64

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

旅行达人必备!有道翻译和这三款神器,轻松走遍世界

在如今的全球化和科技迅猛发展的时代&#xff0c;翻译工具在我们的日常生活中发挥着越来越重要的作用。在各种格式数据的翻译当中&#xff0c;我们就可以发现各种类型的翻译工具纷纷崭露头角。今天就分享三款除了有道翻译外的好用翻译工具&#xff0c;希望可以解决大家翻译的需…

虚幻5|暴击攻击和释放技能,造成伤害

玩家数据的Actor组件制作&#xff1a;虚幻5|制作玩家血量&#xff0c;体力-CSDN博客 造成伤害时&#xff0c;显示暴击及暴击字体颜色和未暴击的字体颜色&#xff0c;还有释放技能连击 一.编辑暴击数据 1.打开之前创建的玩家数据Actor组件 创建一个浮点变量&#xff0c;命名…

从法律风险的角度来看,项目经理遇到不清楚或不明确问题时的处理

大家好&#xff0c;我是不会魔法的兔子&#xff0c;在北京从事律师工作&#xff0c;日常分享项目管理风险预防方面的内容。 序言 在项目开展过程中&#xff0c;有时候会遇到一些不清楚或不明确的状况&#xff0c;但碍于项目进度的紧迫性&#xff0c;不得不硬着头皮做决策&…

喜羊羊教你(如何应对突发的技术故障和危机?)

开发团队如何应对突发的技术故障和危机&#xff1f; 在数字化时代&#xff0c;软件服务的稳定性至关重要。、8月19日下午&#xff0c;网易云音乐疑似出现服务器故障&#xff0c;网页端出现502 Bad Gateway 报错&#xff0c;且App也无法正常使用。 怀疑了自己的电脑、自己的手…

OpenStack 常见模块(二)

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:Linux运维老纪的首页…

MFC工控项目实例之七点击下拉菜单弹出对话框

承接专栏《MFC工控项目实例之六CFile添加菜单栏》 1、在SEAL_PRESSUREDlg.h文件中添加代码 class CSEAL_PRESSUREDlg : public CDialog { ...afx_msg void OnTypeManage(); ... } 2、在SEAL_PRESSUREDlg.cpp文件中添加代码 BEGIN_MESSAGE_MAP(CSEAL_PRESSUREDlg, CDialog)//…

如何使用ssm实现基于Java的学生信息管理系统的设计与实现

TOC ssm165基于Java的学生信息管理系统的设计与实现jsp 绪论 1.1 研究背景 当前社会各行业领域竞争压力非常大&#xff0c;随着当前时代的信息化&#xff0c;科学化发展&#xff0c;让社会各行业领域都争相使用新的信息技术&#xff0c;对行业内的各种相关数据进行科学化&a…

python-随机序列(赛氪OJ)

[题目描述] 小理的作业太多了&#xff0c;怎么也做不完。 小理的数学作业由 T 张试卷组成&#xff0c;每张试卷上有 n 个数 a1..n​ &#xff0c;小理需要算出这些数的极差和方差。极差是一个整数&#xff0c;方差是一个浮点数&#xff0c;要求保留到小数点后 3 位。虽然题目很…

iPhone 手机使用技巧:iPhone 数据恢复软件

无论是由于意外删除、系统崩溃还是软件更新&#xff0c;丢失 iPhone 上的数据都是一场噩梦。从珍贵的照片到重要的工作文件&#xff0c;这种损失可能会让人感到毁灭性。值得庆幸的是&#xff0c;几个 iPhone 数据恢复软件选项可以帮助您找回丢失的文件。这些工具提供不同的功能…

大学数据库系统原理 Mysql数据库实验记录

软件版本说明&#xff1a; 1.Mysql数据库&#xff1a;sql server8.0 2.命令实现使用以及数据库可视化查看&#xff1a;Navicat 16 #不用Mysql Command Line 的原因是不喜欢那个黑框&#xff0c;也不常用&#xff0c;使用Navicat的MYSQL命令列界面是一样的 另外说明 实现相同…

Junit单元测试笔记

常用mock类框架 在软件测试和开发过程中&#xff0c;Mock框架扮演着至关重要的角色&#xff0c;它们允许开发者模拟对象的行为&#xff0c;以便在不需要实际依赖的情况下进行测试。以下是一些常用的Mock框架&#xff1a; MockitoPowerMockEasyMockJMockSpock 初始化mock/spy…

解决ONENOTE复制文字到外部为图片(Ditto)

默认情况下&#xff0c;在ONENOTE中记录的文字&#xff0c;在复制粘贴到外部时&#xff0c;会成为一张图片格式 如下图这段文字&#xff0c;粘贴到QQ中变为了图片 解决办法&#xff1a;安装Ditto Ditto下载链接 点击Download下载 双击安装.exe&#xff0c;选择安装路径后&…

JVM上篇:内存与垃圾回收篇-07-方法区

笔记来源&#xff1a;尚硅谷 JVM 全套教程&#xff0c;百万播放&#xff0c;全网巅峰&#xff08;宋红康详解 java 虚拟机&#xff09; 文章目录 7. 方法区7.1. 栈、堆、方法区的交互关系7.2. 方法区的理解7.2.1. 方法区在哪里&#xff1f;7.2.2. 方法区的基本理解7.2.3. HotSp…

编译 wolfssl 库

wolfssl github: https://github.com/wolfSSL/wolfssl 编译 .lib 或者 .dll wolfssl 很好的提供了 win32 的工程》sln 文件 这样就不用折腾 CMakeLists 文件了&#xff0c;使用 Visual Studio 打开 sln 文件后&#xff0c;设置好 Static 编译库即可&#xff0c;开箱即用 编译 .…

项目开始后,拒绝客户提出的新需求是否会违约?

大家好&#xff0c;我是不会魔法的兔子&#xff0c;在北京从事律师工作&#xff0c;日常分享项目管理风险预防方面的内容。 序言 当一个项目已经开展后&#xff0c;对于项目组而言&#xff0c;最难以忍受的可能要数需求突然发生变化了&#xff0c;尤其是在项目已经进行一半或…

【Netty】Netty时间轮实践与源码解析

目录 定时任务JDK定时任务Timer原理 ScheduledThreadPoolExecutor 时间轮算法netty时间轮架构 netty时间轮 源码解析基本使用HashedWheelTimer 初始化createWheel 创建HashedWheelBucket数组 newTimeout 添加任务执行任务时间轮的优缺点 品一品优秀设计实际的生产环境选择 定时…

css中块,行内块,行内元素转换

参考 元素作用范围 块元素 会在显示时自动换行&#xff0c;例如p标签div等 行内元素 例如span&#xff0c;可以认为是一个不换行的块&#xff0c;其他还有label等 行内块元素 例如img标签显示图片&#xff0c;但不换行 区别 块元素可以设置宽高&#xff0c;但行元素不…

C/C++语言基础--结构体知识详解(包括:结构体数组、字节对齐、位段等内容)

本专栏目的 更新C/C的基础语法&#xff0c;包括C的一些新特性 前言 C语言地结构体是核心内容之一&#xff0c;他运行自定义数据类型&#xff0c;可以将不同地数据类型当作成一个整体&#xff0c;变成一个数据类型&#xff0c;运用及其广泛欢迎点赞 收藏 关注&#xff0c;本…

UE管理内容 —— Alembic File Importer

目录 从Maya导出ABC缓存 导入ABC到UE 导入为静态网格体 导入为几何体缓存 导入为Skeletal Alembic文件格式(.abc)是一个开放的计算机图形交换框架&#xff0c;将复杂的动画化场景浓缩成一组非过程式的、与应用程序无关的烘焙几何结果&#xff1b;可以在外部自由地创建复杂…

如何查看ubuntu版本

在当前的技术环境中&#xff0c;了解操作系统的具体版本对于用户来说至关重要。这不仅能确保软件兼容性&#xff0c;还有助于进行系统管理和故障排查。对于使用Ubuntu系统的用户来说&#xff0c;有几种不同的方法可以查看当前系统的版本。下面将详细介绍如何查看您的Ubuntu系统…