精简CUDA教程——CUDA Driver API

精简CUDA教程——CUDA Driver API

tensorRT从零起步迈向高性能工业级部署(就业导向) 课程笔记,讲师讲的不错,可以去看原视频支持下。

Driver API概述

CUDA 的多级 API

CUDA 的 API 有多级(下图),详细可参考:CUDA环境详解。

  • CUDA Driver API 是 CUDA 与 GPU 沟通的驱动级底层 API。早期 CUDA 与 GPU 沟通都是直接通过 Driver API。cuCtxCreate()cu 开头的基本都是 Driver API。我们熟悉的 nvidia-smi 命令就是调用的 Driver API。
  • 后来发觉 Driver API 太过底层,细节太过复杂,故演变出了 Runtime API,Runtime API 是基于 Driver API 开发的,常见的 cudaMalloc() 等 API 都是 Runtime API。

在这里插入图片描述

CUDA Driver

环境相关

CUDA Driver 是随着显卡驱动发布,要与 cudatoolkit 分开看

CUDA Driver 对应于 cuda.hlibcuda.so 两个文件。注意 cuda.h 会在安装 cudatoolkit 时包含,但是 libcuda.so 是随着显卡驱动安装的我们的系统中的(而不是也跟着 cudatooklit 安装)。因此,如果要直接复制移动 libcuda.so 文件时要注意驱动版本需要与之适配。

如何了解CUDA Driver

本精简课程对于底层的 Driver API 的理解,是为了有利于后续的 Runtime API 的学习与错误调试。Driver API 是理解 cudaRuntime 中上下文的关键。因此,本精简课程在 CUDA Driver 这部分的主要的知识点是:

  • Context 的管理机制
  • CUDA 系列接口的开发习惯(错误检查方法)
  • 内存模型

关于context和内存的分类

关于context,有两种:

  1. 手动管理的 contextcuCtxCreate ,手动管理,以堆栈的方式 push/pop
  2. 自动管理的 contextcuDevicePrimaryCtxRetain,自动管理,Runtime API 以此为基础

关于内存,有两大类:

  1. CPU 内存,称之为 Host Memory
    • Pageable Memory:可分页内存
    • Page-Locked Memory:页锁定内存
  2. GPU 内存(显存),称之为 Device Memory
    • Global Memory:全局内存
    • Shared Memory:共享内存
    • … 其他

以上内容之后会展开介绍。

cuIint 驱动初始化

  1. cuInit 的意义是,初始化驱动 API,全局执行一次即可,如果不执行,则所有 API 都将返回错误。
  2. 没有对应的 cuDestroy,不需要释放,程序销毁自动释放。

返回值检查

版本一

正确友好地检查 cuda 函数的返回值,有利于程序的组织结构,使得代码的可读性更好,错误更容易发现。

我们知道 cuInit 返回的类型是 CUresult,该返回值会告诉程序员函数成功还是失败,失败的原因是什么。

官方版本的检查的逻辑,如下:

// 使用有参宏定义检查cuda driver是否被正常初始化, 并定位程序出错的文件名、行数和错误信息
// 宏定义中带do...while循环可保证程序的正确性
#define checkDriver(op)    \do{                    \auto code = (op);  \if(code != CUresult::CUDA_SUCCESS){     \const char* err_name = nullptr;     \const char* err_message = nullptr;  \cuGetErrorName(code, &err_name);    \cuGetErrorString(code, &err_message);   \printf("%s:%d  %s failed. \n  code = %s, message = %s\n", __FILE__, __LINE__, #op, err_name, err_message);   \return -1;   \}                \}while(0)

是一个宏定义,我们在调用其他 API 的时候,对函数的返回值进行检查,并在出错时将错误码和报错信息打印出来,方便调试。比如:

checkDriver(cuDeviceGetName(device_name, sizeof(device_name), device));

如果有未初始化等错误,报错信息会被清晰地打印出来。

这个版本一也是 Nvidia 官方使用的版本,但是存在一些问题,比如代码可读性较差,直接返回 int 型错误码等。推荐使用版本二。

版本二

// 很明显,这种代码封装方式,更加的便于使用
//宏定义 #define <宏名>(<参数表>) <宏体>
#define checkDriver(op)  __check_cuda_driver((op), #op, __FILE__, __LINE__)bool __check_cuda_driver(CUresult code, const char* op, const char* file, int line){if(code != CUresult::CUDA_SUCCESS){    const char* err_name = nullptr;    const char* err_message = nullptr;  cuGetErrorName(code, &err_name);    cuGetErrorString(code, &err_message);   printf("%s:%d  %s failed. \n  code = %s, message = %s\n", file, line, op, err_name, err_message);   return false;}return true;
}

很明显的,版本二的返回值、代码可读性、封装性等都相较版本一好了很多。使用的方式是一样的:

checkDriver(cuDeviceGetName(device_name, sizeof(device_name), device));
// 或加一个判断,遇到错误即退出
if (!checkDriver(cuDeviceGetName(device_name, sizeof(device_name), device))) {return -1;
}

CUcontext

手动上下文管理

  • context 是一种上下文,关联对 GPU 的所有操作。

  • 一个 context 与一块显卡关联,一块显卡可以被多个 context 关联。

  • 每个线程都有一个栈结构存储 context,栈顶是当前使用的 context,对应有 push/pop 函数操作 context 的栈,所有 API 都以当前 context 为操作目标

试想一下,如果执行任何操作你都需要传递一个 device 决定送到哪个设备执行,得多麻烦。context 就是为了方便管理当前 API 是在哪个 device 上执行而提出的一种手段,而栈结构的使用则是为了保存之前的上下文中的 device,从而方便控制多个设备。

在这里插入图片描述

自动上下文管理

  • 由于高频操作都是一个线程固定访问一个 device 不变,不经常会有同一个线程来回多次访问不同 device 的情况,且只会使用到一个 context,很少用到多 context。
  • 即在多数情况下, CreateContextPushCurrentPopCurrent 这种多 context 管理就显得很麻烦
  • 因此就推出了 cuDevicePrimaryCtxRetain ,为设备关联主 context,这样分配、设置、释放、栈都不需要我们再去手动管理,是一种自动管理 context 的方式
  • primaryContext :给我设备 id,给你 context 并设置好,此时一个 device 对应一个 primary context。不同线程,只要设备 id 相同,primary context 就相同,且 context 是线程安全的。
  • 在之后要介绍的 CUDA Runtime API 中,就是自动使用 cuDevicePrimaryCtxRetain 的。

在这里插入图片描述

DriverAPI 内存管理

  1. host memory 是计算机本身的内存,可以用 CUDA Driver API 来申请和释放,也可以用 C/C++ 的 malloc/freenew/delete 来申请和释放。
  2. device memory 是显卡上的内存,即显存,有专用的 Driver API 来进行申请和释放。

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

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

相关文章

CUDA编程入门极简教程

CUDA编程入门极简教程 转自&#xff1a;CUDA编程入门极简教程 作者&#xff1a;小小将 前言 2006年&#xff0c;NVIDIA公司发布了CUDA&#xff0c;CUDA是建立在NVIDIA的CPUs上的一个通用并行计算平台和编程模型&#xff0c;基于CUDA编程可以利用GPUs的并行计算引擎来更加高效地…

精简CUDA教程——CUDA Runtime API

精简CUDA教程——CUDA Runtime API tensorRT从零起步迈向高性能工业级部署&#xff08;就业导向&#xff09; 课程笔记&#xff0c;讲师讲的不错&#xff0c;可以去看原视频支持下。 Runtime API 概述 环境 图中可以看到&#xff0c;Runtime API 是基于 Driver API 之上开发的…

Python并发——concurrent.futures梳理

Python并发——concurrent.futures梳理 参考官方文档&#xff1a; concurrent.futures — 启动并行任务 Executor对象 class concurrent.funtures.Executor该抽象类是 ThreadPoolExecutor 和 ProcessPoolExecutor 的父类&#xff0c;提供异步执行调用方法。要通过它的子类调用…

TensorRT ONNX 基础

TensorRT ONNX 基础 tensorRT从零起步迈向高性能工业级部署&#xff08;就业导向&#xff09; 课程笔记&#xff0c;讲师讲的不错&#xff0c;可以去看原视频支持下。 概述 TensorRT 的核心在于对模型算子的优化&#xff08;合并算子、利用当前 GPU 特性选择特定的核函数等多种…

回文子串、回文子序列相关题目

回文子串、回文子序列相关题目 回文子串是要连续的&#xff0c;回文子序列可不是连续的。 516. 最长回文子序列 dp数组含义&#xff1a;dp[i][j]dp[i][j]dp[i][j] 表示子序列 s[i,j]s[i,j]s[i,j] 中的最长回文子序列的长度。 dp数组初始化&#xff1a;子序列长度为 1 时&am…

mmdetection tools工具梳理

mmdetection tools工具梳理 mmdetection 是一个非常好用的开源目标检测框架&#xff0c;我们可以用它方便地训练自己的目标检测模型&#xff0c;mmdetection 项目仓库提供许多实用的工具来实现帮助我们进行各种测试。本篇将梳理以下 mmdetection 项目仓库 tools 目录下的各种实…

TensorRT ONNX 基础(续)

TensorRT ONNX 基础&#xff08;续&#xff09; PyTorch正确导出ONNX 几条推荐的原则&#xff0c;可以减少潜在的错误&#xff1a; 对于任何使用到 shape、size 返回值的参数时&#xff0c;例如 tensor.view(tensor.size(0), -1) 这类操作&#xff0c;避免直接使用 tensor.s…

frp实现内网穿透极简教程

frp实现内网穿透极简教程 本文是内网穿透极简教程&#xff0c;为求简洁&#xff0c;我们不介绍为什么内网穿透也不介绍其原理&#xff0c;这里假设各位读者都已经明确的知道自己的目的&#xff0c;本文仅介绍如何安装配置 frp 实现内网穿透。 简单来说&#xff0c;内网穿透就…

图像预处理之warpaffine与双线性插值及其高性能实现

图像预处理之warpaffine与双线性插值及其高性能实现 视频讲解&#xff1a;https://www.bilibili.com/video/BV1ZU4y1A7EG 代码Repo&#xff1a;https://github.com/shouxieai/tensorRT_Pro 本文为视频讲解的个人笔记。 warpaffine矩阵变换 对于坐标点的变换&#xff0c;我们通…

LeetCode-10 正则表达式匹配

LeetCode-10 正则表达式匹配 动态规划 10. 正则表达式匹配 dp数组含义&#xff1a;dp[i][j]dp[i][j]dp[i][j] 表示 s[0:i−1]s[0:i-1]s[0:i−1] 能否被 p[0:j−1]p[0:j-1]p[0:j−1] 成功匹配。 状态转移方程 &#xff1a; 如果 s[i−1]p[j−1]s[i-1]p[j-1]s[i−1]p[j−1] …

shell if判断和for循环常见写法

shell if判断和for循环常见写法 转自&#xff1a; Shell中for循环的几个常用写法 Shell中if 条件判断总结 if常见写法 一、if的基本语法: if [ command ];then符合该条件执行的语句 elif [ command ];then符合该条件执行的语句 else符合该条件执行的语句 fibash shell会按顺序…

关于pytorch使用多个dataloader并使用zip和cycle来进行循环时出现的显存泄漏的问题

关于pytorch使用多个dataloader并使用zip和cycle来进行循环时出现的显存泄漏的问题 如果我们想要在 Pytorch 中同时迭代两个 dataloader 来处理数据&#xff0c;会有两种情况&#xff1a;一是我们按照较短的 dataloader 来迭代&#xff0c;长的 dataloader 超过的部分就丢弃掉…

neovim及coc.nvim自动补全初探

neovim及coc.nvim自动补全初探 安装 # mac # 安装 brew install neovim # 查看neovim安装路径 brew list nvim# ubuntu apt install neovim习惯了打开 vi/vim 的方式&#xff0c;可以用个 alias 在 ~/.zshrc 中设置一下&#xff1a; alias vi"nvim"插件 vim-plug…

sed 简明教程

sed 简明教程 转自&#xff1a;https://coolshell.cn/articles/9104.html awk于1977年出生&#xff0c;今年36岁本命年&#xff0c;sed比awk大2-3岁&#xff0c;awk就像林妹妹&#xff0c;sed就是宝玉哥哥了。所以 林妹妹跳了个Topless&#xff0c;他的哥哥sed坐不住了&#xf…

awk 简明教程

awk 简明教程 转自&#xff1a;https://coolshell.cn/articles/9070.html 有一些网友看了前两天的《Linux下应该知道的技巧》希望我能教教他们用awk和sed&#xff0c;所以&#xff0c;出现了这篇文章。我估计这些80后的年轻朋友可能对awk/sed这类上古神器有点陌生了&#xff0c…

应该知道的LINUX技巧

应该知道的LINUX技巧 转自&#xff1a;https://coolshell.cn/articles/8883.html 这篇文章来源于Quroa的一个问答《What are some time-saving tips that every Linux user should know?》—— Linux用户有哪些应该知道的提高效率的技巧。我觉得挺好的&#xff0c;总结得比较好…

[深度][PyTorch] DDP系列第一篇:入门教程

[深度][PyTorch] DDP系列第一篇&#xff1a;入门教程 转自&#xff1a;[原创][深度][PyTorch] DDP系列第一篇&#xff1a;入门教程 概览 想要让你的PyTorch神经网络在多卡环境上跑得又快又好&#xff1f;那你definitely需要这一篇&#xff01; No one knows DDP better than I…

[深度][PyTorch] DDP系列第二篇:实现原理与源代码解析

[深度][PyTorch] DDP系列第二篇&#xff1a;实现原理与源代码解析 转自&#xff1a;https://zhuanlan.zhihu.com/p/187610959 概览 想要让你的PyTorch神经网络在多卡环境上跑得又快又好&#xff1f;那你definitely需要这一篇&#xff01; No one knows DDP better than I do! …

[深度][PyTorch] DDP系列第三篇:实战与技巧

[深度][PyTorch] DDP系列第三篇&#xff1a;实战与技巧 转自&#xff1a;https://zhuanlan.zhihu.com/p/250471767 零. 概览 想要让你的PyTorch神经网络在多卡环境上跑得又快又好&#xff1f;那你definitely需要这一篇&#xff01; No one knows DDP better than I do! – – …

PIL、OpenCV中resize算子实现不同的问题

PIL、OpenCV中resize算子实现不同的问题 测试图像&#xff1a;https://raw.githubusercontent.com/TropComplique/ssd-pytorch/master/images/dogs-and-cats.jpg &#xff08;直接 wget 可获得&#xff09; 测试版本&#xff1a; opencv-python 4.4.0.46Pillow 8.0.1 测试代…