3.3.内存的学习,pinnedmemory,内存效率问题

目录

    • 前言
    • 1. Memory
    • 总结

前言

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

本次课程学习精简 CUDA 教程-内存模型,pinned memory,内存效率问题

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

在这里插入图片描述

1. Memory

内存模型是 CUDA 中很重要的知识点,通常和高性能有关系。

主要理解 pinned memory(Host Memory)、global memory(Deivce Memory)、shared memory(Device memory)即可,其它不常用

在这里插入图片描述

图1-1 CUDA内存模型

下图展示了显卡中各种内存所处位置,这是一个不太严谨但是辅助理解的图

在这里插入图片描述

图1-2 显卡各种内存位置

其中 shared memory 为片上内存,global memory 为片外内存

显卡的内存即 GPU 内存和主机的内存即 CPU 内存在电脑主板中的位置如下

在这里插入图片描述

图1-3 电脑主板中的GPU和CPU内存

Host Memory 即主机内存如下图所示:

在这里插入图片描述

图1-4 Host Memory

对于整个 Host Memory 内存条而言,操作系统区分为两个大类(逻辑区分,物理上是同一个东西):

  1. Pageable Memory,可分页内存
  2. Page lock Memory,页锁定内存

你可以理解为 Page lock Memory 是 VIP 房间,锁定给你一个人用。而 Pageable Memory 是普通房间,在酒店房间不够的时候,选择性的把你的房间腾出来给其他人交换用(交换到硬盘上),这就可以容纳更多人了。造成房间很多的假象,代价是性能降低

基于前面的理解,我们总结如下:

  1. pinned memory 具有锁定特性,是稳定不会被交换的(这点很重要,相当于每次去这个房间都一定能找到你)
  2. pageable memory 没有锁定特性,对于第三方设备(比如GPU),去访问时,因为无法感知内存是否被交换,可能得不到正确的数据(每次去房间找,说不准你的房间被人交换了)
  3. pageable memory 的性能比 pinned memory 差,很可能降低你程序的优先级然后把内存交换给别人用
  4. pageable memory 策略能使用内存假象,实际是 8GB 但是可以使用 15GB,提高程序运行数量(不是速度)
  5. pinned memory 太多,会导致操作系统整体性能降低(程序运行数量减少),8GB 就只能用 8GB
  6. GPU 可以直接访问 pinned memory 而不能访问 pageable memory

不同的 Host Memory 数据传输到 GPU 上的方式不同,具体如下图所示:

在这里插入图片描述

图1-5 Pinned Memory和Pageable Memory数据传输到GPU

GPU 要访问 Pageable Memory 的数据必须通过 Pinned Memory,GPU 可以直接访问 Pinned Memory 数据,其轨迹主要是通过 PICE 接口到主板再到内存条。

内存方面知识点总结

原则

  1. GPU 可以直接访问 pinned memory,称之为 DMA(Direct Memory Access) 技术
  2. 对于 GPU 访问而言,距离计算单元越近,效率越高,所以 Pinned Memory<Global Memory<Shared Memory
  3. 代码中,由 new、malloc 分配的是 pageable Memory,由 cudaMallocHost 分配的是 Pinned Memory(C语言函数分配也行),由 cudaMalloc 分配的是 Global Memory
  4. 尽量多用 Pinned Memory 储存 host 数据或者显式处理 Host 到 Device 时用 Pinned Memory 做缓存都是提高性能的关键

内存模型案例代码如下:

// CUDA运行时头文件
#include <cuda_runtime.h>#include <stdio.h>
#include <string.h>#define checkRuntime(op)  __check_cuda_runtime((op), #op, __FILE__, __LINE__)bool __check_cuda_runtime(cudaError_t code, const char* op, const char* file, int line){if(code != cudaSuccess){    const char* err_name = cudaGetErrorName(code);    const char* err_message = cudaGetErrorString(code);  printf("runtime error %s:%d  %s failed. \n  code = %s, message = %s\n", file, line, op, err_name, err_message);   return false;}return true;
}int main(){int device_id = 0;checkRuntime(cudaSetDevice(device_id));float* memory_device = nullptr;checkRuntime(cudaMalloc(&memory_device, 100 * sizeof(float))); // pointer to devicefloat* memory_host = new float[100];memory_host[2] = 520.25;checkRuntime(cudaMemcpy(memory_device, memory_host, sizeof(float) * 100, cudaMemcpyHostToDevice)); // 返回的地址是开辟的device地址,存放在memory_devicefloat* memory_page_locked = nullptr;checkRuntime(cudaMallocHost(&memory_page_locked, 100 * sizeof(float))); // 返回的地址是被开辟的pin memory的地址,存放在memory_page_lockedcheckRuntime(cudaMemcpy(memory_page_locked, memory_device, sizeof(float) * 100, cudaMemcpyDeviceToHost)); // printf("%f\n", memory_page_locked[2]);checkRuntime(cudaFreeHost(memory_page_locked));delete [] memory_host;checkRuntime(cudaFree(memory_device)); return 0;
}

运行效果如下:

在这里插入图片描述

图1-6 Memory案例

代码演示了操作内存分配和数据复制,整个流程可用下面的示意图来说明。先创建三个指针(mem_device、mem_host、mem_page_locked),然后开辟三块空间,将 mem_host 的数据复制到 GPU 上,再将 GPU 上 mem_deivce 的数据复制回 mem_page_locked 上(绿色箭头代表拷贝方向)

在这里插入图片描述

图1-7 数据传输示意图

关于内存模型及其知识点(from 杜老师)

1.关于内存模型,请参照https://www.bilibili.com/video/BV1jX4y1w7Um

  • 内存大局上分为
  • 主机内存:Host Memory,也就是 CPU 内存,内存
  • 设备内存:Device Memory,也就是 GPU 内存,显存
    • 设备内存又分为:
      • 全局内存(3):Global Memory(√)
      • 寄存器内存(1):Register Memory
      • 纹理内存(2):Texture Memory
      • 共享内存(2):Shared Memory(√)
      • 常量内存(2):Constant Memory
      • 本地内存(3):Local Memory
    • 只需要知道,谁距离计算芯片近,谁速度越快,空间越小,价格越贵
      • 清单的括号数字表示到计算芯片的距离

2.通过 cudaMalloc 分配 GPU 内存,分配到 setDevice 指定的当前设备上

3.通过 cudaMallocHost 分配 page locked memory,即 pinned memory,页锁定内存

  • 页锁定内存是主机内存,CPU 可以直接访问
  • 页锁定内存也可以被 GPU 直接访问,使用 DMA(Direct Memory Access)技术
  • 注意这么做的性能会比较差,因为主机内存距离 GPU 太远,隔着 PCIE 等,不适合大量数据传输
  • 页锁定内存是物理内存,过度使用会导致系统性能地低下(导致虚拟内存等一系列技术变慢)

4.cudaMemcpy

  • 如果 host 不是页锁定内存,则:
  • Device To Host 的过程,等价于:
    • pinned = cudaMallocHost
    • copy Device to Host
    • copy pinned to Host
    • free pinned
  • Host To Device 的过程,等价于:
    • pinned = cudaMallocHost
    • copy Host to pinned
    • copy pinned to Device
    • free pinned
  • 如果 host 是页锁定内存,则:
  • Device To Host 的过程,等价于
    • copy Device to Host
  • Host To Device 的过程,等价于
    • copy Host to Device

对于分配的内存一般来说建议先分配的先释放

checkRuntime(cudaFreeHost(memory_page_locked));
delete [] memory_host;
checkRuntime(cudaFree(memory_device));

使用 CUDA API 来分配内存的一般都有自己对应的释放内存方法;而使用 new 来分配的则使用 delete 来释放

总结

本次课程简单的学习了下各种内存,其中主机内存(即 CPU 内存)需要了解 pinned memory 以及 page locked memory 两大类,设备内存(即 GPU 内存)需要知道 Global memory 和 shared memory。同时页锁定内存可以直接被 GPU 访问(DMA技术),cudaMallocHost 分配的是页锁定内存(pinned memory),new、malloc 分配的是可分页内存(pageable memory),cudaMallo 分配的是 Global Memory。
两大类,设备内存(即 GPU 内存)需要知道 Global memory 和 shared memory。同时页锁定内存可以直接被 GPU 访问(DMA技术),cudaMallocHost 分配的是页锁定内存(pinned memory),new、malloc 分配的是可分页内存(pageable memory),cudaMallo 分配的是 Global Memory。

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

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

相关文章

双非本大二上岸大厂——念念不忘,必有回响

⭐️前言⭐️ 博主就读于一所普通的学校&#xff08;双非本&#xff09;&#xff0c;在大二下学期3月份开始网上投递简历&#xff0c;历时近百余天&#xff0c;投递简历500&#xff0c;面试近40余场&#xff0c;最终在6月份学期末&#xff0c;斩获了两个大厂offer&#xff08;北…

windows环境安装robotframework-ride

在Windows环境下&#xff0c;可以通过以下步骤安装Robot Framework RIDE&#xff1a; 安装Python 首先&#xff0c;需要在Windows环境下安装Python。建议使用Python 3.x版本&#xff0c;可以从官方网站下载并安装&#xff1a;https://www.python.org/downloads/windows/ 安装w…

剑指offer27.二叉树的镜像

这道题很简单&#xff0c;写了十多分钟就写出来了&#xff0c;一看题目就知道这道题肯定要用递归。先交换左孩子和右孩子&#xff0c;再用递归交换左孩子的左孩子和右孩子&#xff0c;交换右孩子的左孩子和右孩子&#xff0c;其中做一下空判断就行。以下是我的代码&#xff1a;…

传输方式的分类【图解TCP/IP(笔记五)】

文章目录 传输方式的分类面向有连接型和无连接型面向有连接型面向无连接型 电路交换与分组交换根据接收端数量分类单播&#xff08;Unicast&#xff09;广播&#xff08;Broadcast&#xff09;多播&#xff08;Multicast&#xff09;任播&#xff08;Anycast&#xff09; 传输方…

[VUE学习]权限管理系统前端vue实现8-右上角用户头像显示实现

1.登录成功之后存储 用户信息 在store里面添加代码 SET_USERINFO: (state, userInfo) > {sessionStorage.setItem("userInfo", JSON.stringify(userInfo))},GET_USERINFO: state > {return JSON.parse(sessionStorage.getItem("userInfo"))} 2.Logi…

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

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

区间dp(动态规划)

动态规划——区间dp 什么是动态规划区间dp定义应用 例题引入题目描述输入格式输出格式样例样例输入样例输出 提示 贪心法区间dp优缺点&#xff1a;AC代码&#xff1a;代码详解三层for循环状态转移方程环形的处理 什么是动态规划 动态规划&#xff08;dp&#xff09;是一种通过…

使用Gradio库创建交互式散点图

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

Javaee技术目的总结

一.前节回顾 在前一节中&#xff0c;我们了解了&#xff1a; 1.将中央控制器中的Action容器&#xff0c;变成可控制! 2.针对于反射调用业务代码&#xff0c;最终页面跳转 3.jsp页面参数传递后台的代码优化字段太多有影响&#xff01; 二.项目部署前期准备工作 1.项目运行环境…

分布式运用——监控平台 Zabbix

分布式运用——监控平台 Zabbix 一、Zabbix概述1.监控平台的作用2.Zabbix 是什么&#xff1f;3.Zabbix的特点4.Zabbix的使用场景5.Zabbix 监控原理6.Zabbix 6.0 新特性7.Zabbix 6.0 功能组件①.Zabbix Server②.数据库③.Web 界面④.Zabbix Agent⑤.Zabbix Proxy⑥.Java Gatewa…

爬虫反反爬

目录 为什么要反爬&#xff1f; 经常被反爬的主要人群 常见的反爬策略 通过headers字段来反爬 通过headers中的User-Agent字段来反爬 通过referer字段或者是其他字段来反爬 通过cookie来反爬 通过请求参数来反爬 通过从html静态文件中获取请求数据(github登录数据) 通…

Kafka入门, 消费者组案例(十九)

pom 文件 <dependencies><dependency><groupId>org.apache.kafka</groupId><artifactId>kafka-clients</artifactId><version>3.0.0</version></dependency></dependencies>独立消费者案例&#xff08;订阅主语&a…