【并行计算】CUDA基础

2024-09-04 19:52
文章标签 基础 cuda 并行计算

本文主要是介绍【并行计算】CUDA基础,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

cuda程序的后缀:.cu

编译:nvcc hello_world.cu

执行:./hello_world.cu

使用语言还是C++。

1. 核函数

__global__ void add(int *a, int *b, int *c) {*c = *a + *b;
}

核函数只能访问GPU的内存。也就是显存。CPU的存储它是碰不到的。

并且核函数不能使用变长参数、静态变量、函数指针。

核函数具有异步性。GPU无法控制CPU,CPU也不会去等GPU,所以需要同步,也就是显式调用同步函数。有些线程也是需要同步的。

编写CUDA程序:

int main(void){主机代码核函数调用主机代码return 0;
}

核函数不支持C++的iostream。

#include<stdio.h>
__global__ void hello_from_gpu(){printf("Hello from GPU!\n");__syncthreads();// 显式同步
}
int main(){hello_from_gpu<<<1,1>>>();// 显式调用核函数cudaDeviceSynchronize();// 显式同步return 0;
}

2. 线程块

int main() {int a = 1;int b = 2;int c;add<<<1, 1>>>(&a, &b, &c);return 0;
}

线程模型重要概念:

  1. grid网格
  2. block线程块

线程分块是逻辑上的划分,物理上线程不分块。

配置线程:<<<grid_num, block_num>>>

第一个参数代表着我们有M个线程块,第二个参数代表着我们的每个线程块中有N个线程。他们都是一维的。这昂个参数保存在内建变量(build-in variable)中。

gridDim.x: 该变量的数值等于执行配置中变量grid_num的值。

blockDim.x: 该变量的数值等于执行配置中变量block_num的值。

最大允许线程块的大小为1024。最大允许的网格大小是 2 3 1 − 1 2^31-1 2311(针对一维网格)。

实际使用中,总线程数大于实际使用的线程数能更好地利用计算资源,因为这样可以使得GPU在计算的时候内存访问同时进行,节省计算机计算的时间。使得核心一直处于计算中。

启动核函数后,CPU并不会等待核函数执行完毕,立马去执行主机中其他程序。所以我们要做的就是使得这两部分时间重叠。

3. 线程块的索引

int main() {int a = 1;int b = 2;int c;add<<<1, 1>>>(&a, &b, &c);return 0;
}

线程索引保存成内s建变量(build-in variable):

  1. blockIdx.x: 该变量指定一个线程在一个网格中的线程块索引值,范围0-girdDim.x-1。
  2. threadIdx.x: 该变量指定一个线程在线程块中的索引值,范围0-blockDim.x-1。

线程具有唯一标识:

I d x = t h r e a d I d x . x + b l o c k D i m . x ∗ b l o c k I d x . x ; Idx = threadIdx.x + blockDim.x * blockIdx.x; Idx=threadIdx.x+blockDim.xblockIdx.x;

4. 推广到多维线程

  1. CUDA可以组织三维的网格和线程块;

  2. blockIdx和threadIdx是类型为uint3的变量,该类型是一个结构体,具有x,y,z三个成员(3个成员都为无符号类型的成员构成):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 定义多维网格和线程块(C++构造函数语法):

dim3 grid_num(Gx,Gy,Gz);
dim3 block_num(Bx,By,Bz);

dim3 grid_num(2,2); // 等价于dim3 grid_num(2,2,1);
dim3 block_num(5,3); // 等价于dim3 block_num(5,3,1);

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5. 一维网格 一维线程块

定义grid和block尺寸:

dim3 grid_num(4);
dim3 block_num(8);

调用核函数:

kernel_fun<<<grid_num, block_num>>>(…);

具体的线程索引方式如图所示。

blockIdx.x从0到3,threadIdx.x从0到7。

计算方式:

I d x = t h r e a d I d x . x + b l o c k D i m . x ∗ b l o c k I d x . x ; Idx = threadIdx.x + blockDim.x * blockIdx.x; Idx=threadIdx.x+blockDim.xblockIdx.x;

6. 二维网格 二维线程块

定义grid和block尺寸:

dim3 grid_num(2,2);
dim3 block_num(5,3);

调用核函数:

kernel_fun<<<grid_num, block_num>>>(…);

具体的线程索引方式如图所示。

blockIdx.x从0到1,threadIdx.y从0到1。

blockIdx.x从0到1,threadIdx.y从0到3。

计算方式:

i n t b l o c k I d = b l o c k I d x . x + g r i d D i m . x ∗ b l o c k I d x . y ; i n t t h r e a d I d = t h r e a d I d x . x + b l o c k D i m . x ∗ t h r e a d I d x . y ; i n t i d = b l o c k I d ∗ ( b l o c k D i m . x ∗ b l o c k D i m . y ) + t h r e a d I d ; int blockId = blockIdx.x + gridDim.x * blockIdx.y; int threadId = threadIdx.x + blockDim.x * threadIdx.y; int id = blockId * (blockDim.x * blockDim.y) + threadId; intblockId=blockIdx.x+gridDim.xblockIdx.y;intthreadId=threadIdx.x+blockDim.xthreadIdx.y;intid=blockId(blockDim.xblockDim.y)+threadId;

7. 三维网格 三维线程块

定义grid和block尺寸:

dim3 grid_num(2,2,2);
dim3 block_num(5,3,1);

调用核函数:

kernel_fun<<<grid_num, block_num>>>(…);

具体的线程索引方式如图所示。

blockIdx.x、blockIdx.y和blcokIdx.z从0到1,

threadIdx.x、threadIdx.y从0到3,threadIdx.z从0到1。

计算方式:

i n t b l o c k I d = b l o c k I d x . x + g r i d D i m . x ∗ b l o c k I d x . y + g r i d D i m . x ∗ g r i d D i m . y ∗ b l o c k I d x . z ; i n t t h r e a d I d = ( t h r e a d I d x . z ∗ ( b l o c k D i m . x ∗ b l o c k D i m . y ) ) + ( t h r e a d I d x . y ∗ b l o c k D i m . x ) + t h r e a d I d x . x ; i n t i d = b l o c k I d ∗ ( b l o c k D i m . x ∗ b l o c k D i m . y ∗ b l o c k D i m . z ) + t h r e a d I d ; int blockId = blockIdx.x + gridDim.x * blockIdx.y + gridDim.x * gridDim.y * blockIdx.z; int threadId= (threadIdx.z * (blockDim.x * blockDim.y) ) + (threadIdx.y * blockDim.x) + threadIdx.x; int id = blockId * (blockDim.x * blockDim.y * blockDim.z) + threadId; intblockId=blockIdx.x+gridDim.xblockIdx.y+gridDim.xgridDim.yblockIdx.z;intthreadId=(threadIdx.z(blockDim.xblockDim.y))+(threadIdx.yblockDim.x)+threadIdx.x;intid=blockId(blockDim.xblockDim.yblockDim.z)+threadId;

三维网格、三维线程块如图所示:

https://github.com/user-attachments/assets/c57924c1-2157-4c73-87ea-36f6842e9eff

Reference

[1]. 权双.CUDA编程基础入门系列(持续更新)[M/OL](2023-07-14)[2024-08-21].https://www.bilibili.com/video/BV1sM4y1x7of/?p=7&share_source=copy_web&vd_source=8b2bc57e71349607b55c9fde6b078ebd

这篇关于【并行计算】CUDA基础的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1136871

相关文章

从基础到高级详解Python数值格式化输出的完全指南

《从基础到高级详解Python数值格式化输出的完全指南》在数据分析、金融计算和科学报告领域,数值格式化是提升可读性和专业性的关键技术,本文将深入解析Python中数值格式化输出的相关方法,感兴趣的小伙... 目录引言:数值格式化的核心价值一、基础格式化方法1.1 三种核心格式化方式对比1.2 基础格式化示例

redis-sentinel基础概念及部署流程

《redis-sentinel基础概念及部署流程》RedisSentinel是Redis的高可用解决方案,通过监控主从节点、自动故障转移、通知机制及配置提供,实现集群故障恢复与服务持续可用,核心组件包... 目录一. 引言二. 核心功能三. 核心组件四. 故障转移流程五. 服务部署六. sentinel部署

从基础到进阶详解Python条件判断的实用指南

《从基础到进阶详解Python条件判断的实用指南》本文将通过15个实战案例,带你大家掌握条件判断的核心技巧,并从基础语法到高级应用一网打尽,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录​引言:条件判断为何如此重要一、基础语法:三行代码构建决策系统二、多条件分支:elif的魔法三、

Python WebSockets 库从基础到实战使用举例

《PythonWebSockets库从基础到实战使用举例》WebSocket是一种全双工、持久化的网络通信协议,适用于需要低延迟的应用,如实时聊天、股票行情推送、在线协作、多人游戏等,本文给大家介... 目录1. 引言2. 为什么使用 WebSocket?3. 安装 WebSockets 库4. 使用 We

从基础到高阶详解Python多态实战应用指南

《从基础到高阶详解Python多态实战应用指南》这篇文章主要从基础到高阶为大家详细介绍Python中多态的相关应用与技巧,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、多态的本质:python的“鸭子类型”哲学二、多态的三大实战场景场景1:数据处理管道——统一处理不同数据格式

MySQL数据类型与表操作全指南( 从基础到高级实践)

《MySQL数据类型与表操作全指南(从基础到高级实践)》本文详解MySQL数据类型分类(数值、日期/时间、字符串)及表操作(创建、修改、维护),涵盖优化技巧如数据类型选择、备份、分区,强调规范设计与... 目录mysql数据类型详解数值类型日期时间类型字符串类型表操作全解析创建表修改表结构添加列修改列删除列

Python 函数详解:从基础语法到高级使用技巧

《Python函数详解:从基础语法到高级使用技巧》本文基于实例代码,全面讲解Python函数的定义、参数传递、变量作用域及类型标注等知识点,帮助初学者快速掌握函数的使用技巧,感兴趣的朋友跟随小编一起... 目录一、函数的基本概念与作用二、函数的定义与调用1. 无参函数2. 带参函数3. 带返回值的函数4.

python panda库从基础到高级操作分析

《pythonpanda库从基础到高级操作分析》本文介绍了Pandas库的核心功能,包括处理结构化数据的Series和DataFrame数据结构,数据读取、清洗、分组聚合、合并、时间序列分析及大数据... 目录1. Pandas 概述2. 基本操作:数据读取与查看3. 索引操作:精准定位数据4. Group

从基础到进阶详解Pandas时间数据处理指南

《从基础到进阶详解Pandas时间数据处理指南》Pandas构建了完整的时间数据处理生态,核心由四个基础类构成,Timestamp,DatetimeIndex,Period和Timedelta,下面我... 目录1. 时间数据类型与基础操作1.1 核心时间对象体系1.2 时间数据生成技巧2. 时间索引与数据

安装centos8设置基础软件仓库时出错的解决方案

《安装centos8设置基础软件仓库时出错的解决方案》:本文主要介绍安装centos8设置基础软件仓库时出错的解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录安装Centos8设置基础软件仓库时出错版本 8版本 8.2.200android4版本 javas