【NVIDIA CUDA】2023 CUDA夏令营编程模型(一)

news2025/1/20 15:53:45

博主未授权任何人或组织机构转载博主任何原创文章,感谢各位对原创的支持!
博主链接

本人就职于国际知名终端厂商,负责modem芯片研发。
在5G早期负责终端数据业务层、核心网相关的开发工作,目前牵头6G算力网络技术标准研究。


博客内容主要围绕:
       5G/6G协议讲解
       算力网络讲解(云计算,边缘计算,端计算)
       高级C语言讲解
       Rust语言讲解

文章目录

  • CUDA编程模型
    • 一、异构计算术语
    • 二、CUDA安装
      • 2.1 适用设备
      • 2.2 软件安装
      • 2.3 查看当前设备参数
      • 2.4 CUDA程序示例
    • 三、CUDA程序的编写
    • 四、CUDA关键字介绍
      • 4.1 \_\_global__关键字
      • 4.2 \_\_device__关键字
      • 4.3 \_\_host__关键字
    • 五、CUDA程序的编写
    • 五、CUDA线程层次
    • 六、CUDA内存操作
      • 6.1 内存分配
      • 6.2 内存拷贝
      • 6.3 内存释放
    • 七、获取CUDA线程索引
    • 八、CUDA 的线程分配
    • 九、GPU的存储单元
    • 十、CUDA错误检测
    • 十一、CUDA统一内存(Unified Memory)
    • 十二、CUDA事件
    • 十三、NVPROF



CUDA编程模型

一、异构计算术语

Host:CPU和内存(host memory)
Device:CPU和内存(host memory)

在这里插入图片描述

二、CUDA安装

2.1 适用设备

所有包含NVIDIA GPU的服务器,工作站,个人电脑,嵌入式设备等电子设备

2.2 软件安装

  • Windows:https://docs.nvidia.com/cuda/cuda-installation-guide-microsoft-windows/index.html
    只需安装一个.exe的可执行程序
  • Linux:https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html
    按照上面的教程,需要6 / 7 个步骤即可
  • Jetson: https://developer.nvidia.com/embedded/jetpack
    直接利用NVIDIA SDK Manager 或者 SD image进行刷机即可

2.3 查看当前设备参数

在CUDA sample中1_Utilities/deviceQuery文件夹下的deviceQuery程序。以Ubuntu为例,deviceQuery 程序
在:/usr/local/cuda/samples/1_Utilities/deviceQu

2.4 CUDA程序示例

https://github.com/NVIDIA/cuda-samples

三、CUDA程序的编写

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、CUDA关键字介绍

4.1 __global__关键字

__global__执行空间说明符将函数声明为内核。 它的功能是:

  • 在设备上执行;
  • 可从主机调用,可在计算能力为 3.2或更高的设备调用;
  • __global__ 函数必须具有 void 返回类型,并且不能是类的成员;
  • global 函数的任何调用都必须指定其执行配置;
  • global 函数的调用是异步的,这意味着它在设备完成执行之前返回;

4.2 __device__关键字

__device__ 执行空间说明符声明了一个函数:

  • 在设备上执行;
  • 只能从设备调用;
  • __global__ 和 __device__ 执行空间说明符不能一起使用;

4.3 __host__关键字

__host__ 执行空间说明符声明了一个函数:

  • 在主机上执行;
  • 只能从主机调用;
  • __global__ 和 __host__ 执行空间说明符不能一起使用。但是, __device__ 和 __host__ 执行空间说明
    符可以一起使用,在这种情况下,该函数是为主机和设备编译的;

五、CUDA程序的编写

在这里插入图片描述

  • __global__ 定义一个 kernel 函数
    • 入口函数,CPU上调用,GPU上执行;
    • 必须返回void;
  • __device__ and __host__ 可以同时使用

在这里插入图片描述

五、CUDA线程层次

HelloFromGPU <<<grid_size, block_size>>>();

  • Thread: sequential execution unit
    • 所有线程执行相同的核函数
    • 并行执行
  • Thread Block: a group of threads
    • 执行在一个Streaming Multiprocessor (SM)
    • 同一个Block中的线程可以协作
  • Thread Grid: a collection of thread blocks
    • 一个Grid当中的Block可以在多个SM中执行
  • 内建变量
    • threadIdx.[x y z]:是执行当前kernel函数的线程在block中的索引值;
    • blockIdx.[x y z]:是指执行当前kernel函数的线程所在block,在grid中的索引值;
    • blockDim.[x y z]:表示一个block中包含多少个线程;
    • gridDim.[x y z]:表示一个grid中包含多少个block;

例如,dim3 grid(3,2,1), block(5,3,1)的线程分布示意图:
在这里插入图片描述

一个cuda线程在一个cuda core上执行,一个block在一个sm上执行,一个grid在整个device上执行,但是反之不成立。
在这里插入图片描述

六、CUDA内存操作

6.1 内存分配

__host__ __device__ cudaError_t cudaMalloc(void** devPtr, size_t size)

  • devPtr:Pointer to allocated device memory
  • Size:Requested allocation size in bytes

6.2 内存拷贝

cudaMemcpy(void *dst, const void *src, size_t count, cudaMemcpyKind kind)

  • dst: destination memory address
  • src: source memory address
  • count: size in bytes to copy
  • kind: direction of the copy
    • cudaMemcpyKind
      • cudaMemcpyHostToDevice
      • cudaMemcpyDeviceToHost
      • cudaMemcpyDeviceToDevice
      • cudaMemcpyHostToHost

6.3 内存释放

cudaFree()

七、获取CUDA线程索引

对于一维数据来说:
在这里插入图片描述

对于二维数据来说:
在这里插入图片描述

八、CUDA 的线程分配

一个warp包含32个cuda线程,所以一个block会被分成一个或多个warp执行。
在这里插入图片描述

九、GPU的存储单元

在这里插入图片描述

十、CUDA错误检测

在这里插入图片描述
在这里插入图片描述
注意:
cudaGetLastError(void)cudaPeekAtLastError(void)的区别是,调用cudaGetLastError(void)之后,会将错误类型重置为cudaSuccess,然后调用cudaPeekAtLastError(void)后不会修改cudaError_t的状态。可以从下面的例子中看出来:

在这里插入图片描述
一个通用的cuda error检测宏:
在这里插入图片描述

十一、CUDA统一内存(Unified Memory)

统一内存是可从系统中的任何处理器访问的单个内存地址空间。这种硬件/软件技术允许应用程序分配可以从
CPU s 或 GPUs 上运行的代码读取或写入的数据。分配统一内存非常简单,只需将对 malloc() 或 new 的调用替换
为对 cudaMallocManaged() 的调用,这是一个分配函数,返回可从任何处理器访问的指针。

在这里插入图片描述
分配Unified Memory有两种方法:

  1. cudaError_t cudaMallocManaged(void **devPtr, size_t size, unsigned int flags=0)
    在这里插入图片描述

  2. 使用关键字__managed__
    在这里插入图片描述

使用了统一内存之后并不意味之CPU和GPU使用了同一块内存空间。如下图所示,如果GPU要访问的页面已经在GPU Memory中,则没有任何异常;如果GPU要访问的页面不在当前的GPU Memory中,则将CPU Memory中的page迁移到GPU Memory中。
在这里插入图片描述
统一内存的优势:

  • 可直接访问CPU内存、GPU显存,不需要手动拷贝数据;
  • CUDA 在现有的内存池结构上增加了一个统一内存系统,程序员可以直接访问任何内存/显存资源,或者在合法
    的内存空间内寻址,而不用管涉及到的到底是内存还是显存;
  • CUDA 的数据拷贝由程序员的手动转移,变成自动执行,因此,它仍然受制于PCI-E的带宽和延迟;

十二、CUDA事件

CUDA event本质是一个GPU时间戳,这个时间戳是在用户指定的时间点上记录的。由于GPU本身支持记录时间戳,因此就避免了当使用CPU定时器来统计GPU执行时间可能遇到的诸多问题。

在这里插入图片描述
如何使用上述事件函数:

  1. 声明:
    cudaEvent_t event;

  2. 创建:
    cudaError_t cudaEventCreate(cudaEvent_t* event);

  3. 添加事件到当前执行流:
    cudaError_t cudaEventRecord(cudaEvent_t event, cudaStream_t stream
    = 0);

  4. 等待事件完成,设立flag:
    cudaError_t cudaEventSynchronize(cudaEvent_t event);//阻塞
    cudaError_t cudaEventQuery(cudaEvent_t event);//非阻塞

    当然,我们也可以用它来记录执行的事件:
    cudaError_t cudaEventElapsedTime(float* ms, cudaEvent_t start,
    cudaEvent_t stop);

    cudaEventRecord()视为一条记录当前时间的语句,并且把这条语句放入GPU的未完成队列中。因为直到GPU执行完了再调用 cudaEventRecord()之前的所有语句时,事件才会被记录下来。且仅当GPU完成了之前的工作并且记录了stop事件后,才能安全地读取stop时间值。

  5. 销毁:
    cudaError_t cudaEventDestroy(cudaEvent_t event);

代码示例:

cudaEvent_t start, stop;
cudaEventCreate( &start );
cudaEventCreate( &stop ) ;
cudaEventRecord( start) ;
// GPU
//
//.........................
cudaEventRecord( stop)
cudaEventSynchronize( stop );
float elapsedTime;
cudaEventElapsedTime( &elapsedTime,start, stop ) );
printf( "Time to generate: %.2f ms\n", elapsedTime );
cudaEventDestroy( start );
cudaEventDestroy( stop );

十三、NVPROF

Kernel Timeline 输出的是以gpu kernel 为单位的一段时间的运行时间线,我们可以通过它观察GPU在什么时候有闲置或者利用不够充分的行为,更准确地定位优化问题。nvprof是nvidia提供的用于生成gpu timeline的工具,其为cuda toolkit的自带工具。

非常方便的分析工具!
nvprof -o out.nvvp a.exe

可以结合nvvp或者nsight进行可视化分析
https://docs.nvidia.com/cuda/profiler-users-guide/index.html#nvprof-overview



在这里插入图片描述

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

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

相关文章

【Git】Git GitHub

1. Git1.1 Git基本操作1.2 Git版本回退1.3 Git分支操作 2. Git 配合GitHub2.1 生成密钥2.2 GitHub添加公钥2.3 Git连接GitHub2.4 本地仓库关联远程仓库2.5 本地代码push远程仓库2.6 本地clone远程仓库2.7 本地fetch和pull 1. Git 1.1 Git基本操作 touch test.py 工作区创建文…

全网最细,Postman接口测试实战详细总结,一篇进阶...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 Postman是一款功能…

【力扣每日一题】2023.7.30 环形链表2

题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 这道题属于是那种知道解法就很简单&#xff0c;不知道解法就很难独立想出来的那种&#xff0c;我们只需要稍微记住这类题的固定解法就可以。 所以接下来我先说解法&#xff0c;再解释为什么解法可以解出来。 那么我们都…

nginx使用-(想学nginx,这篇就够了)

nginx使用-&#xff08;想学nginx&#xff0c;这篇就够了&#xff09; upstream wgz{server 127.0.0.1:8081 ;server 127.0.0.1:8082 ;fair;}反向代理 动静分离 负载均衡 高可用集群配置 反向代理 upstream要转发的地址的配置proxy_pass请求转发的地址 location /user{proxy_…

程序设计 算法基础

✅作者简介&#xff1a;人工智能专业本科在读&#xff0c;喜欢计算机与编程&#xff0c;写博客记录自己的学习历程。 &#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&…

【并发专题】操作系统模型及三级缓存架构

目录 课程内容一、冯诺依曼计算机模型详解1.计算机五大核心组成部分2.CPU内部结构3.CPU缓存结构4.CPU读取存储器数据过程5.CPU为何要有高速缓存 学习总结 课程内容 一、冯诺依曼计算机模型详解 现代计算机模型是基于-冯诺依曼计算机模型 计算机在运行时&#xff0c;先从内存中…

python学习之【浅拷贝】

前言 上一篇文章&#xff0c;python学习之【继承、封装、多态】主要学习了面向对象的三大特征。这篇文章记录下对python的浅拷贝的学习&#xff0c;下一篇文章接着学习深拷贝。 简单了解 浅拷贝&#xff1a;python拷贝一般都是浅拷贝&#xff0c;拷贝时&#xff0c;对象包含的…

【C语言】函数重难点之函数递归

大家好&#xff0c;我是深鱼~ 目录 一、函数递归知识讲解 1.什么是递归&#xff1f; 2.递归的两个必要条件 2.1练习1&#xff1a; 2.2练习2&#xff1a; 二、递归与迭代 2.1练习3 2.2练习4 一、函数递归知识讲解 1.什么是递归&#xff1f; 程序调用自身的编程技巧称为…

UNITY随记(八) SHADER实现立方体CUBE显示边框,描边

Shader "Vitens/CubeOutline"{Properties{_Color("Color", color) = (1,1,1,1)_Width("Width", range(0,0.5)) = 0.1}SubShader{Tags {"Queue"=

windows下载安装FFmpeg

FFmpeg是一款强大的音视频处理软件&#xff0c;下面介绍如何在windows下下载安装FFmpeg 下载 进入官网: https://ffmpeg.org/download.html, 选择Windows, 然后选择"Windows builds from gyan.dev" 在弹出的界面中找到release builds, 然后选择一个版本&#xff0…

Java中的生产者/消费者模型

一、什么是生产者/消费者模型 生产者-消费者模型&#xff08;Producer-Consumer problem&#xff09;是一个非常经典的多线程并发协作的模型。 比如某个模块负责生产数据&#xff0c;而另一个模块负责处理数据。产生数据的模块就形象地被称为生产者&#xff1b;而处理数据的模…

基地培训一周总结-用两台虚拟机模拟公司和员工

前言&#xff1a; 本来是打算每天跟更新所学内容&#xff0c;但奈何自己接触新知识速度较慢&#xff0c;每天都在完不成任务的边缘疯狂试探&#xff0c;短时间大量知识的涌入&#xff0c;感觉脑袋瓜在有点 跟不上。这周结束的时候&#xff0c;老师布置了个小项目&#xff0c;融…

Linux操作系统下安装python环境

参考&#xff1a;Linux操作系统下安装python环境_linux如何下载python_秃头小猿-F的博客-CSDN博客 注意 切换用户 二、切换root用户 1.给root用户设置密码&#xff1a;命令&#xff1a;sudo passwd root输入密码&#xff0c;并确认密码。2.重新输入命令&#xff1a;su root …

【数据结构】之十分好用的“链表”赶紧学起来!(第一部分单向链表)

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

某行动态cookie反爬虫分析

某行动态cookie反爬虫分析 1. 预览 反爬网址(base64): aHR0cDovL3d3dy5wYmMuZ292LmNu 反爬截图&#xff1a; 需要先加载运行js代码&#xff0c;可能是对环境进行检测&#xff0c;反调试之类的 无限debugger 处理办法 网上大部分人说的都是添加cookie来解决。 那个noscrip…

哈工大计算机网络课程网络安全基本原理之:身份认证

哈工大计算机网络课程网络安全基本原理之&#xff1a;身份认证 在日常生活中&#xff0c;在很多场景下我们都需要对当前身份做认证&#xff0c;比如使用密码、人脸识别、指纹识别等&#xff0c;这些都是身份认证的常用方式。本节介绍的身份认证&#xff0c;是在计算机网络安全…

flask处理表单数据

flask处理表单数据 处理表单数据在任何 web 应用开发中都是一个常见的需求。在 Flask 中&#xff0c;你可以使用 request 对象来获取通过 HTTP 请求发送的数据。对于 POST 请求&#xff0c;可以通过 request.form 访问表单数据。例如&#xff1a; from flask import Flask, r…

设置Fiddler来抓取Android接口数据

1.下载安装fiddler&#xff0c;安装包可自行百度。安装完成打开fiddler 2.将Fiddler设置远程访问PC 选择Fiddler->Tools->Fiddler Option 3.选择Connection&#xff0c;在Fiddler listen on port后输入8888&#xff0c;表示允许远程PC连接。 4.在电脑运行窗口中&#xf…

Leetcode145. 二叉树的后序遍历

题目描述 题目链接&#xff1a;https://leetcode.cn/problems/binary-tree-postorder-traversal/description/ 代码实现 class Solution {List<Integer> tree new ArrayList<>();public List<Integer> postorderTraversal(TreeNode root) {postorder(ro…