C++学习|CUDA编程入门

news2025/2/27 12:57:32

CUDA编程入门

  • GPU介绍
  • CUDA 介绍
  • NVCC——CUDA编译器
  • cu/cuh文件——CUDA文件
  • 核函数——操作GPU
  • 线程模型——CUDA逻辑结构
  • CUDA程序运行流程
  • CUDA内存管理

GPU介绍

GPU(Graphics Processing Unit,图形处理器,显卡):最早主要是进行图形处理,现在已经被广泛应用于深度学习,最大的优势就是高效的并行计算能力。

GPU和CPU的区别:

  • 结构上来说,虽然CPU和GPU都有控制单元、运算单元和缓存,但是CPU需要大量空间存放控制单元和缓存,而GPU中运算单元占了大部分。
  • 功能上来说,由于结构上占比,所以CPU在大规模并行计算能力上极受限制,而更擅长逻辑控制。而GPU有数量众多的计算单元和超长的流水线,非常适合计算海量同类型处理的数据。

为什么要用GPU:GPU比CPU的优势在于能提供高性能的并行运算,对于大规模同类型数据处理,可以通过算法并行优化来提高运行效率。

CUDA 介绍

CUDA(Compute Unified Device Architecture):2006年,NIVIDIA公司发布了CUDA。CUDA是操作GPU计算的硬件和软件的架构,提供了GPU编程的简易接口。

CUDA支持多语言:C/C++、Python、Fortran等。

CUDA提供两层API接口:CUDA驱动(Driver)和CUDA运行时(Runtime)API。两者调用性能几乎差异不大,但Runtime API使用更加友好。因为Driver API 可以通过直接操作硬件执行一些复杂的功能,Runtime API 对 Driver API 进行了一定的封装,隐藏了部分实现细节。
在这里插入图片描述

NVCC——CUDA编译器

NVCC:NVCC是CUDA的编译器,位于bin/目录中。

工作流程:CUDA程序是包含主机(Host)代码和设备(Device)代码的统一源代码,Host代码在CPU运行,Device代码在GPU运行。NVCC编译器在编译过程中将两者区分开来,Host代码是用C语言编译的,那么就会交给C编译器进一步编译,以一个CPU进程的方式运行;Device代码用C扩展语言编写,GPU运行的核函数(后面有介绍核函数)代码会由NVCC进一步编译并在GPU上执行。

cu/cuh文件——CUDA文件

cu/cuh文件:cu和cuh都是CUDA的后缀格式。cu文件只是含有CUDA代码的cpp文件,cuh相当于CUDA的头文件后缀名。

CUDA文件里面可以包含Host代码和Device代码。

核函数——操作GPU

核函数(Kernel function):核函数在GPU上进行并行执行。

函数编写形式:

  • 限定词:“__global__”修饰。
  • 返回值:返回值必须是void。
  • 文件:在.cu文件中编写。
__global__ void func(argument arg)
{
	printf("GPU: Hellow World\n");
}

编写注意事项:

  • 核函数只能访问GPU内存。GPU和CPU之间内存是要通过特定API才能进行交互的。
  • 核函数不能使用变长参数、静态变量和函数指针。
  • 核函数具有异步性。CPU不会等GPU核函数运行完了才继续。

核函数的调用:使用“<<<grid_size,block_size>>>”来调用线程执行核函数,grid、block和线程的概念会在线程模型里面详细解释。

int main(void){
	func<<<1, 1>>>();
	return 0;
}

线程模型——CUDA逻辑结构

CUDA 的并行计算:通过成千上万个线程(Thread)的并行执行来实现。

线程模型Thread(线程)、Block(线程块)、Grid(网格)三者关系:如下图所示,Thread组成Block,Block组成Grid,Kernel执行的时候启动的是一个Grid。这些线程块的划分都是逻辑上,并不是物理上,划分是为了方便编写代码。
在这里插入图片描述
理解核函数调用:这时候其实就能理解前面核函数的“<<<grid_size,block_size>>>”调用,grid_size参数指的是一个Grid里面有多少个Block,block_size参数指的是一个Block里面有多少个线程。参数grid_size×block_size就是线程数量,可以理解为有多少个一模一样的函数线程在同时跑。

func<<<1, 1>>>();//输出一次:GPU: Hellow World,因为有1个线程。
func<<<2, 4>>>();//输出八次:GPU: Hellow World,因为有8个线程。

多维线程:前面代码部分提到的都是一维的Grid和Block,但Grid和Block可以不止一维甚至最多能到三维。例如在上面线程模型图中,Grid和Block里面的结构都是二维的,从索引的坐标可以看得出来。在执行核函数前,用dim3变量规定一下grid_size和block_size参数的维度就行了。

dim3 grid_size(2,2);//二维
dim3 block_size(16, 16, 2);//三维
func<<<grids, blocks>>>();

线程索引:每个线程都会一个唯一编号标识。下面示范一个二维Grid和二维Block的线程索引计算,可以配合上面的线程模型图理解。

// blockIdx、threadIdx都是unit3类型,表示它们的坐标。
// gridDim、blockDime都是dim3类型,表示网格的大小。
int blockId=blockIdx.x+blockId.y*gridDim.x;// block在grid的ID
int threadId=threadIdx.y*blockDim.x+threadIdx.x;// thread在block的ID
int id=blockId*(blockDim.x*blockDim.y)+threadId;// thread在grid的ID

为什么要有多维线程:主要是为了简化一些三维建模以及二维图像处理的问题。例如二维图片做图像处理,每个核函数要对图片像素进行操作,但是传入的是图片的矩阵,那么核函数还需要计算出自己处理的是那个像素。这个时候因为block结构本身就是二维,可以直接用thread本身的x和y来索引。如果block结构是一维的,还得花很多心思去调整偏移量和步幅来找到要处理的像素。

// 多维线程实现矩阵加法
__global__ void MatAdd(int A[N][N], int B[N][N], int C[N][N]){
    int x = threadIdx.x;// 在block中线程的x坐标
    int y = threadIdx.y;// 在block中线程的y坐标
    C[x][y] = A[x][y] + B[x][y];
}
 
int main(){
	...
    int grid_size = 1;
    dim3 block_size(N,N);
    MatAdd<<<grid_size,block_size>>>(A,B,C);
    ...
}

CUDA程序运行流程

  1. CPU初始化:分配 Host 内存,并进行数据初始化。
  2. GPU初始化:分配 Device 内存,并从 Host 将数据拷贝到 Device 上。
  3. GPU并行运算:调用 CUDA 的核函数在 Device 上完成指定的运算。
  4. 结果从GPU传回CPU:将 Device上的运算结果拷贝到 Host 上。
  5. 初始化清空:释放 Device 和 Host 上分配的内存。

CUDA内存管理

了解了CUDA程序运行流程,复杂的CUDA程序会涉及到CPU和GPU之间的数据交互。CPU和GPU之间的数据是不共享的,所以需要分配、拷贝、传递以及释放。

功能函数
内存分配cudaMalloc
数据传递cudaMemcpy
内存初始化cudaMemset
内存释放cudaFree

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

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

相关文章

第三方电容笔支持随手写吗?开学季平价好用电容笔

作为一个苹果的忠实粉丝&#xff0c;我知道很多关于数码产品的事情。而电容笔&#xff0c;也是iPad平板的一个重要配件之一&#xff0c;许多人购买iPad后&#xff0c;都希望拥有一支好用的电容笔&#xff0c;但又不知道如何选择。本人用过30余款电容笔&#xff0c;为方便各位朋…

C++信息学奥赛1142:单词的长度

#include <iostream> #include <string> using namespace std; int main() {string str1;// 输入一行字符串getline(cin,str1);int n0;for(int i0;i<str1.length();i){if(str1[i] ){while (str1[i1] ){i; // 跳过连续的空格}cout<<n<<","…

js传参没有反应

js反应如果传的参是字符串, 则不能直接传, 需要加上双引号 下面这种是传数值的形式:

【java】【idea2023版】Springboot模块没有.iml文件的问题

目录 方法一&#xff1a; 1、首先鼠标选中对应的对应的模块 &#xff0c;按两下Ctrl键 2、project中选择对应的模块 3、运行mvn idea:module 命令​编辑 方法二&#xff1a; 1、可以右键点击open Terminal 2、然后在打开的Terminal里输入 方法一&#xff1a; 1、首先鼠…

基于HarmonyOS ArkUI实现音乐列表功能

本节将演示如何在基于HarmonyOS ArkUI的List组件来实现音乐列表功能。 本文涉及的所有源码&#xff0c;均可以在文末链接中找到。 活动主页 华为开发者论坛 规则要求具体要求如下&#xff1a; 第1步&#xff1a;观看<HarmonyOS第一课>“营”在暑期•系列直播&#x…

冠达管理股票分析:数据资产入表规定落地 算力产业化加速在即

8月22日&#xff0c;算力龙头股鸿博股份股价强势涨停。方针面上&#xff0c;财政部日前拟定印发了《企业数据资源相关管帐处理暂行规则》。业内人士表明&#xff0c;数据财物入表规则落地将极大推进数据运营变现。这能改进和优化企业的财物负债表和损益表&#xff0c;更有利于促…

Android 使用模拟器模拟Linux操作系统

1. 简介 在Android手机上使用模拟器模拟ubuntu等操作系统&#xff0c;便于测试 2. 软件准备 Termux&#xff1a;是一款 Android 终端模拟器和 Linux 环境应用程序&#xff0c;无需 root 或设置即可直接运行。虽然酷安和谷歌菜市场都能下载&#xff0c;但这些渠道都很久没更新…

YOLOv5屏蔽区域检测(选择区域检测)

YOLOv5屏蔽区域检测以及选择区域检测 前期准备labelme选择mask区域 代码改动 前期准备 思路就是通过一个mask掩膜&#xff0c;对我们想要屏蔽或者选择的区域进行遮挡处理&#xff0c;在推理的时候&#xff0c;将有mask掩膜的图像输入&#xff0c;将最后的结果显示在原始图像上…

Spring学习之【DefaultListableBeanFactory】

介绍 BeanFactory是个Factory&#xff0c;也就是IOC容器或对象工厂&#xff0c;而DefaultListableBeanFactory是Bean工厂的一个默认实现&#xff0c;DefaultListableBeanFactory提供了原始的BeanFactory的功能&#xff0c;如&#xff1a;对外提供getbean()方法&#xff0c;维护…

科技爆炸,白领办公新style,工作吩咐一声,电脑自动完成

“骂醒恋爱脑”的公司月入六七万&#xff1f;在刚刚过去的七夕&#xff0c;这个新闻可算硬核。 但对于直球程序员来说“恋爱脑”不一定存在&#xff0c;而赛博朋克级的浪漫可以说是独一份。 利用大模型&#xff0c;小帅为女友策划完美七夕&#xff0c;一声吩咐下&#xff0c;…

初识 Redis

初识 Redis 1 认识NoSQL1.1 结构化与非结构化1.2 关联和非关联1.3 查询方式1.4. 事务1.5 总结 2 Redis 概述2.1 应用场景2.2 特性 3 Resis 全局命令4 Redis 基本数据类型4.1 String4.1.1 常用命令4.1.2 命令的时间复杂度4.1.3 使用场景 4.2 Hash4.2.1 常用命令4.2.2 命令的时间…

这个实用连锁店高效技巧,让便利店工作更省心!

当今社会&#xff0c;随着科技的不断进步&#xff0c;视频监控技术正逐渐渗透到我们生活的方方面面。无论是在公共场所、商业建筑、交通系统还是家庭环境&#xff0c;我们都可以见到摄像头的身影。 对于连锁企业而言&#xff0c;视频监控已经成为一项不可或缺的管理工具&#x…

抖音seo短视频矩阵系统源代码开发原型--开源

一、系统设计 1.需求分析 抖音SEO矩阵系统的主要功能是提高视频的曝光和排名&#xff0c;因此&#xff0c;其主要需求包括&#xff1a; 1&#xff09;关键词研究&#xff1a;通过分析用户搜索行为&#xff0c;挖掘出热门关键词&#xff0c;以便制定针对性的SEO策略。 2&…

无需繁琐算量计算,鹏业安装算量软件帮你搞定!

亲爱的朋友们&#xff0c;大家好&#xff01;今天非常高兴为大家带来一款极具智能、专业和效率的算量神器——鹏业安装算量软件&#xff01;这款软件将彻底改变你的算量工作方式&#xff0c;让你轻松完成各种预算、审计和施工任务。 首先&#xff0c;鹏业安装算量软件自动识别图…

数字孪生引领智慧港口新纪元

随着数字化时代的到来&#xff0c;港口行业也在不断寻求创新&#xff0c;以提高运营效率、优化资源分配&#xff0c;并实现可持续发展。数字孪生技术作为一种强大的虚拟仿真工具&#xff0c;正日益成为智慧港口解决方案的核心。本文带大家一起探讨数字孪生在智慧港口领域的应用…

gdb call 函数调用

在 gdb 里可以用 call 命令来调用函数&#xff0c;跟代码里调用效果是一样的。在任一断点处都可以用 call 来调用函数&#xff0c;但不知是否需要debug 信息来支持&#xff0c;我这里实际操作的都是带debug信息的程序。首先打一个断点&#xff0c;如&#xff1a; 当断点触发时&…

Java之AbstractQueuedSynchronizer

要让你写一个java版的并发同步库&#xff0c;你会怎么思考设计&#xff1f;&#xff1f;&#xff1f;先思考三五分钟 请先拜读下老外的paperhttp://gee.cs.oswego.edu/dl/papers/aqs.pdf 1. 简介 AbstractQueuedSynchronizer&#xff0c;简称AQS&#xff0c;中文翻译为抽象队…

LeetCode--HOT100题(41)

目录 题目描述&#xff1a;102. 二叉树的层序遍历&#xff08;中等&#xff09;题目接口解题思路代码 PS: 题目描述&#xff1a;102. 二叉树的层序遍历&#xff08;中等&#xff09; 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&am…

【C语言进阶(6)】字符串函数的使用方法 + 模拟实现

文章目录 Ⅰ 字符操作函数⒈字符分类函数⒉字符转换函数 Ⅱ 字符串操作函数⒈strlen⒉strcpy⒊strcat⒋strcmp⒌strncpy⒍strncat⒎strncmp⒏strstr⒐strtok⒑strerror Ⅲ 模拟实现字符串函数⒈模拟实现 strlen⒉模拟实现 strcpy⒊模拟实现 strcat⒋模拟实现 strcmp⒌模拟实现 …

ABB DI651电源模块

数字输入&#xff1a; DI651模块是用于读取数字输入信号的设备。它可以接收来自传感器、开关、按钮等外部设备的数字信号。 信号类型&#xff1a; 这种模块通常可以处理不同类型的数字信号&#xff0c;例如开关信号、脉冲信号、状态信号等。 通道数量&#xff1a; DI651模块可…