2.4.cuda驱动API-使用驱动API进行内存分配

news2024/11/17 23:58:39

目录

    • 前言
    • 1. 内存分配
    • 总结

前言

杜老师推出的 tensorRT从零起步高性能部署 课程,之前有看过一遍,但是没有做笔记,很多东西也忘了。这次重新撸一遍,顺便记记笔记

本次课程学习精简 CUDA 教程-Driver API 内存分配

课程大纲可见下面的思维导图

在这里插入图片描述

1. 内存分配

在这里我们只做一个基本的演示,更多详细的内容我们会在 Runtime API 上讲

使用 Driver API 进行内存分配案例的示例代码如下:

// CUDA驱动头文件cuda.h
#include <cuda.h>

#include <stdio.h>
#include <string.h>

#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;
}

int main(){

    // 检查cuda driver的初始化
    checkDriver(cuInit(0));

    // 创建上下文
    CUcontext context = nullptr;
    CUdevice device = 0;
    checkDriver(cuCtxCreate(&context, CU_CTX_SCHED_AUTO, device));
    printf("context = %p\n", context);

    // 输入device prt向设备要一个100 byte的线性内存,并返回地址
    CUdeviceptr device_memory_pointer = 0;
    checkDriver(cuMemAlloc(&device_memory_pointer, 100)); // 注意这是指向device的pointer, 
    printf("device_memory_pointer = %p\n", device_memory_pointer);

    // 输入二级指针向host要一个100 byte的锁页内存,专供设备访问。参考 2.cuMemAllocHost.jpg 讲解视频:https://v.douyin.com/NrYL5KB/
    float* host_page_locked_memory = nullptr;
    checkDriver(cuMemAllocHost((void**)&host_page_locked_memory, 100));
    printf("host_page_locked_memory = %p\n", host_page_locked_memory);

    // 向page-locked memory 里放数据(仍在CPU上),可以让GPU可快速读取
    host_page_locked_memory[0] = 123;
    printf("host_page_locked_memory[0] = %f\n", host_page_locked_memory[0]);
    /* 
        记住这一点
        host page locked memory 声明的时候为float*型,可以直接转换为device ptr,这才可以送给cuda核函数(利用DMA(Direct Memory Access)技术)
        初始化内存的值: cuMemsetD32 ( CUdeviceptr dstDevice, unsigned int  ui, size_t N )
        初始化值必须是无符号整型,因此需要将new_value进行数据转换:
        但不能直接写为:(int)value,必须写为*(int*)&new_value, 我们来分解一下这条语句的作用:
        1. &new_value获取float new_value的地址
        (int*)将地址从float * 转换为int*以避免64位架构上的精度损失
        *(int*)取消引用地址,最后获取引用的int值
     */
    
    float new_value = 555;
    checkDriver(cuMemsetD32((CUdeviceptr)host_page_locked_memory, *(int*)&new_value, 1)); //??? cuMemset用来干嘛?
    printf("host_page_locked_memory[0] = %f\n", host_page_locked_memory[0]);

    // 释放内存
    checkDriver(cuMemFreeHost(host_page_locked_memory));
    return 0;
}

运行效果如下:

在这里插入图片描述

图1-1 内存分配案例运行效果

这段代码展示了使用 CUDA Driver API 进行设备内存和页锁定内存的分配、访问和释放操作。

首先,代码创建了一个上下文 context,然后使用 cuMemAlloc 函数为 GPU 分配了一个 100 字节的线性内存,并返回了内存的地址。接着,使用 cuMemAllocHost 函数为 CPU 分配了一个 100 字节的页锁定内存,该内存可供 GPU 访问。函数中使用了二级指针,并将其转换成了 void** 类型。之后,代码向页锁定内存中存储了一个值。

接下来,代码使用 cuMemsetD32 函数将页锁定内存中的值进行初始化。该函数的第一个参数是设备指针,需要将 host_page_locked_memory 强制转换为 CUdeviceptr 类型。函数的第二个参数是初始化的值,需要进行数据转换,将 float 类型的值转换为无符号整型。

最后,代码使用 cuMemFreeHost 函数释放了页锁定内存的分配。

关于 cuMemsetD32() 函数有以下几点说明:

  1. host page locked memory 声明的时候为 float* 类型,可以直接转换为 device ptr,只有转换后才可以送到 cuda 核函数(利用DMA(Direct Memory Access)技术)
  2. 初始化内存的值使用的函数:cuMemsetD32(CUdeviceptr dstDevice, unsigned int ui, size_t N)
  3. 初始化值必须是无符号整型,因此需要将 new_value 进行数据转换。但不能直接写 (int)value,必须写 *(int*)&new_value
  4. &new_value 获取 float new_value 的地址,(int*) 将地址从 float * 转换为 int * 避免 64 位架构上的精度损失,*(int *) 取消引用地址,最后获取引用的 int 值
  5. cuMemset 也可以用于在设备内存中设置值,但它设置的是字节数据(unsigned char),而 cuMemsetD32 设置的是 32 位整数数据(unsigned int)

我们注释创建 context 的代码然后再运行下:

在这里插入图片描述

图1-2 context注释报错信息

可以看到程序报错,提示 context 为空,只有当前上下文存在才能做后续的一些操作,

总结

本次课程主要简单讲了下使用 Driver API 进行内存的分配,演示了设备内存、页锁定内存的分配。

Driver API 的学习到这里就结束了,我们不需要有过多的认识,知道 context 是怎么回事,知道 primary context 是怎么回事就行了。

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

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

相关文章

基于Java生活缴费系统设计实现(源码+lw+部署文档+讲解等)

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

【工具】录屏工具Bandicam参数测试(参数设置建议)

一款小而精美的软件&#xff0c;上手特别容易&#xff0c;学习版参见b站up视频&#xff1a;【免费】好用录屏软件推荐&#xff0c;无水印1080P你值得拥有。 我有个需求&#xff0c;要求录屏但视频文件尽可能小但保持基本清晰。 我分别用看视频环境&#xff08;b站学习教程类&…

探索全桥电机驱动模块:实现精确控制与高效驱动

全桥电机驱动模块是一种在现代工程应用中广泛使用的电机驱动方式。对于需要精确控制和高效驱动的场景&#xff0c;如机器人、无人机、电动车等&#xff0c;全桥电机驱动模块提供了理想的解决方案。本文将介绍全桥电机驱动模块的原理和实际应用场景&#xff0c;并对几种常见的全…

【高并发网络通信架构】引入IO多路复用(select,poll,epoll)实现高并发tcp服务端

目录 一&#xff0c;往期文章 二&#xff0c;基本概念 IO多路复用 select 模型 poll 模型 epoll 模型 三&#xff0c;函数清单 1.select 方法 2.poll 方法 3.epoll_create 方法 4.epoll_ctl 方法 5.epoll_wait 方法 6.struct epoll_event 结构体 四&#xff0c;代…

uniapp踩坑之项目:uniapp修改弹窗组件样式

在components文件夹里创建zz-prompt文件夹&#xff0c;再在下面创建index.vue <!--通知弹窗index.vue--> <template><view class"prompt-box" v-if"visible" touchmove"true"><view class"prompt"><view c…

1.8 用户注册_和使用的工具类

步骤1&#xff1a;在common模块下,创建对应的工具类 /** 创建性别枚举(Sex)*/ /** md5加密类(MD5Utils)*/ /** 时间转换格式化类(DateUtil)*/ /** 生成全局唯一主机id (Sid)*/步骤2&#xff1a;在pojo模块下&#xff0c;创建表单封装bo对象 /** 注册表单bo对象 UserBO*/步骤3…

怎么将桌面笔记软件中记录的内容折叠起来或展开显示?

记笔记是一种良好的习惯&#xff0c;不仅可以帮助我们整理思绪&#xff0c;还能有效地记录重要的信息。在现代科技的支持下&#xff0c;一款优秀的笔记软件已经成为我们记录和管理事项的主要工具。特别是一款能够折叠的桌面笔记软件&#xff0c;将会给用户带来更多的便利和效率…

2023.07.07 homework

孩子们有些基础不好&#xff0c;鼓励为主&#xff0c;教他们慢慢搬公式推算&#xff0c;提高准确率就好啦。每一次比上一次好一点点&#xff0c;慢慢找回自信心。 图形结合&#xff0c;话说话&#xff0c;其实数学这玩意&#xff0c;画得好也比较直观 第八题找规律的题目&#…

【如何成功加载 HuggingFace 数据集】不使用Colab,以ChnSentiCorp数据集为例

【如何成功加载 HuggingFace 数据集】不使用Colab&#xff0c;以ChnSentiCorp数据集为例 前置加载数据集尝试一&#xff1a;标准加载数据库代码尝试二&#xff1a;科学上网尝试三&#xff1a;把 Huggingface 的数据库下载到本地尝试3.5 创建 state.json彩蛋 前置 Huggingface …

DAY45——动态规划part7

爬楼梯问题 爬楼梯阶数为1...m class Solution {public int climbStairs(int n) {int[] dp new int[n 1];int m 2;dp[0] 1;for (int i 1; i < n; i) { // 遍历背包for (int j 1; j < m; j) { //遍历物品if (i > j) dp[i] dp[i - j];}}return dp[n];} } class…

基于matlab处理来自立体相机图像数据构建室外环境地图并估计相机的轨迹(附源码)

一、前言 视觉同步定位和映射 &#xff08;vSLAM&#xff09; 是指计算摄像机相对于周围环境的位置和方向&#xff0c;同时映射环境的过程。该过程仅使用来自相机的视觉输入。vSLAM 的应用包括增强现实、机器人和自动驾驶。vSLAM 只需使用单眼摄像头即可执行。但是&#xff0c…

Spring系列3 -- 更简单的读取和存储对象

前言 上一篇章总结了,Spring的创建与使用,通过创建Maven项目配置Spring的环境依赖,创建Spring框架的项目,然后通过在Resource目录下创建Spring-config.xml配置文件,添加<bean></bean>标签将我们需要的bean对象注入到容器中,然后通过ApplicationContext获取Spring上…

Mybatis-puls——条件查询的三种格式+条件查询null判定+查询投影

前言 在mybatis_plus的封装中的Wrapper<T>接口参数就是用于封装查询条件 在测试类中启动如上一个简单的查询&#xff0c;然后控制台运行会输出一大堆无关日志&#xff0c;这里先把这些日志关闭 去除无关日志文件 先新建一个XML配置文件 然后变成如下&#xff0c;这里…

[神经网络]YoloV7

Yolo系列是一类很经典的目标检测网络&#xff0c;属于anchor-base型网络&#xff0c;即需要先产生先验框然后筛选先验框得到预测框。同时它也是One-Stage网络&#xff0c;即不需要额外的网络结构来筛选先验框。这两种特点使得它具备了运算速度快和计算精度相对较高的特点。 比较…

Win10怎么用U盘重装系统?Win10用U盘重装系统步骤图解教程

Win10怎么用U盘重装系统&#xff1f;使用U盘重装系统是一种快速而有效的方法&#xff0c;可以帮助我们在电脑中进行Win10系统的重新安装。首先用户需要准备一个容量适当的U盘&#xff0c;并确保其中没有重要数据&#xff0c;然后按照小编分享的Win10用U盘重装系统步骤图解教程操…

Redis 简单入门

✏️作者&#xff1a;银河罐头 &#x1f4cb;系列专栏&#xff1a;JavaEE &#x1f332;“种一棵树最好的时间是十年前&#xff0c;其次是现在” 目录 安装 Redisredis 的数据类型和使用字符串类型字典类型列表类型集合类型有序集合类型 SpringBoot 集成 Redis添加 redis 依赖配…

el-checkbox / el-checkbox-group中绑定对象无法回显的问题处理

在使用el-checkbox / el-checkbox-group时&#xff0c;发现若label绑定的是对象&#xff0c;则是无法回显的&#xff0c;参考了很多方法&#xff0c;但大多都无法解决&#xff0c;最终参考下面的方法解决&#xff0c;记录一下。 <el-checkbox :label"JSON.stringify(i…

每天一点Python——day51

#第五十一天列表和字典为可变序列&#xff0c;元组是不可变序列 为什么要将元组设计成不可变序列呢&#xff1f; 一旦创建了不可变类型的对象&#xff0c;对象内部的所有数据将不能被修改 这样就避免了由于修改数据而导致的错误 对于不可变对象&#xff0c;在多任务环境下&…

最小覆盖串双指针解题思路及Java实现

最小覆盖串双指针解题思路及Java实现 题目双指针思路Java实现 题目 题目来自牛客NC28 最小覆盖子串 给出两个字符串 s 和 t&#xff0c;要求在 s 中找出最短的包含 t 中所有字符的连续子串。 例如&#xff1a; 输入&#xff1a;“XDOYEZODEYXNZ”,“XYZ” 返回值&#xff1a;“…

使用LiteSpeed缓存插件将WordPress优化到100%的得分

页面速度优化应该是每个网站所有者的首要任务&#xff0c;因为它直接影响WordPress SEO。此外&#xff0c;网站加载的时间越长&#xff0c;其跳出率就越高。这可能会阻止您产生转化并为您的网站带来流量。 使用正确的工具和配置&#xff0c;缓存您的网站可以显着提高其性能。因…