这一系列文章面向CUDA开发者来解读《CUDA C

Best Practices Guide》 (CUDA C最佳实践指南)

大家可以访问:

这是一本很经典的手册。

CUDA优化的冷知识|什么是APOD开发模型?

CUDA优化的冷知识2| 老板对不起

CUDA优化的冷知识 3 |男人跟女人的区别

CUDA优化的冷知识 4 | 打工人的时间是如何计算的

CUDA优化的冷知识 5 | 似是而非的计时方法

CUDA优化的冷知识 6 |GPU端的CUDA Event计时

CUDA优化的冷知识 7 |GPU端Event计时的重要特色

CUDA优化的冷知识 8 |GPU显存的特色

CUDA优化的冷知识9 |GPU显存的粒度

我们下面就继续进一步的, 说说Global Memory的相关优化.

要说对它的优化, 我们得先知道Global Memory是什么, 和很多人的印象里的不同, 它不一定是显存. 还可能是映射的内存. (例如zero-copy时候的手工分配的, 和退化的Unified Memory的情况). 我们主要说一下当Global Memory是显存, 和是zero-copy的情况, 而暂时忽略是退化的Unified Memory的情况。

说一下这两者时候的注意事项和优化.

首先本实践手册这里, 提到了zero-copy内存, 这种是锁定在物理页面中, 而不能被交换到磁盘上, 同时又能被GPU设备, 直接访问到的内存(映射成了global memory)。

这种内存, 具有多个特点.

先说一下实体显卡上的, 再说一下我们的Jetson上的。

在实体显卡上, 因为卡是通过PCI-E连接到CPU的, 此时的一切传输(从内存到显存), 均需要通过PCI-E进行. 而PCI-E的带宽非常有限. 通常只有16GB/s的理论带宽. 注意手册这里第一次给出了实际能达到的, 在PCI-E 3.0 x16下的传输带宽, 往往是只有12GB/s左右, 这个结果是和实际日常使用中的情况是一样的. 手册这里给出的的确是比较准确的数字. 而这个带宽, 很多时候, 只有通过锁定在页面中的缓冲区传输, 才能达到的, 为何? 主要是这个涉及了CUDA C编程指南中, 和CUDA Runtime API手册中的最前面说的一些情况. 我简单这里重复一下吧.

一个是作为PCI-E上的GPU设备, 他用自带的DMA引擎, 进行BUS Mastering的时候, 本身就只能访问物理页面(或者说, 物理页面范围). 而不能支持CPU端的虚拟内存. (否则它将需要理解CPU端的页表结构等一系列问题, 才能自动转换)。我们知道当年的某蓝色巨人的XGA显卡, 作为它的8514显卡的继承人, 具有CPU端的虚拟内存支持, 并重新实现了兼容于x86 CPU的页表和相应的CR寄存器,作为当年的该机型的用户, 超越了20年的感动依然在心中。然而其他所有后来的显卡都没有这个特点, 因此他们就只能用自己的DMA Engines访问物理内存(好吧, 某些DGX例外). 因此, 当用户要求传输一段普通的可换页内存的时候, 要么显卡驱动内部, 先将该段内存缓冲区的内容, 复制到自己内部的一个小的锁定的物理页面范围上去, 然后再从这里安全的传输; 要么就是就地尝试锁定, 然后传输. 但前者多了一次内存内存的传输, 后者则有锁定和解锁开销(这里面的细节可以看CUDA Runtime API手册的前面, 历年GTC也有过详细描述) 。

前者几乎将内存的有效带宽降低了一半,例如我们上次距离的那个68GB/s峰值的内存的机器(4通道DDR4-2133), 这样一倒腾, 内存带宽就实际上只有34GB/s了. 哪怕你不考虑在CPU上运行的应用程序的需要, 光这点带宽, 传输两三张卡就撑不住了,而使用这种锁定了页面的内存, 则可以就地开始传输, 节省了一半的内存的带宽, 因为过程从内存->内存->显存, 变成了内存->显存了. 还是很容易喂饱你的卡们的. 这个是很适合在实体GPU上传输的特性。

这是对于实体卡说的,对于我们的Jetson产品, 实际上是并没有独立的显存和内存的, 也不是通过PCI-E总线传输的, CPU和GPU都在SoC的内部, 共享SoC提供的内存(显存)控制器. 此时如果你照搬之前的经验, 直接来一个cudaMemcpy*()系列函数. 则实际上你无辜的在该内存(显存)内部, 倒腾了一次. 无任何意义. 当时他们提出, 一定要利用页面锁定内存, 能无传输的就地访问的特性(俗称zero-copy, 可以看成是最最简化版的Unified Memory). 取消掉这个在Jetson上的无辜传输. 然后让GPU就地访问CPU的工作数据. 这点还是非常重要的。

不过在Jetson系列产品上, 直接使用zero-copy的方式会禁用GPU的缓存(L2)的, 不如后来的更好用一点(但限制更大)的Jetson上的Unified Memory方式好(也是直接共享, 但启用L2, 但会禁用CPU-GPU同时访问). 这点等我们到了Unified Memory的时候再说。

好了.回到本章节前面的页面锁定内存的传输和作为zero-copy上的特性内容。

注意本章节这里提到了, 要在CUDA 2.2+, 无显存的那种集成显卡上, 使用zero-copy, 云云的. 而没有提到Jetson. 这是因为手册10年来没改的缘故了.

我们现在已经将近10年买不到这种无显存的卡了(以前一些笔记本上有),而Jetson产品也已经普及。

所以我们这里做了调整, 取消了手册上说的过时的不存在的内容, 而增加了Jetson上应当考虑zero-copy就地使用的做法.

此外, 手册上介绍了如何能利用页面锁定的内存, 有效的进行计算和传输重叠的特性. 手册这里给出了一个很好用的东西:

就是当我们只有1个kernel要启动, 和1份缓冲区要使用的时候, 如果能让这个进行多次传输和计算的重叠. 本实践手册这里给出了如下建议: 即将你的kernel修改里面的线程或者block的坐标/下标映射, 将原本一次启动的kernel, 工作于一个大缓冲区上, 改成N次启动(注意每次里面的坐标的变化), 并每次传输1/N内容的缓冲区, 这样可以尽量达到传输和计算的重叠. 这个是一个很好的实践方式. 因为很多时候, 你想利用传输和计算重叠这个优化, 但是你找不到多余的kernel计算任务, 和多余的传输任务来重叠,此时, 你应当考虑本手册中的, 拆分计算规模, 和拆分成1/N每次传输的建议. 这种建议还是很好的. 当然这样做, 你需要注意坐标的偏移和变化. 不要计算错了.

实际上, 在某OpenCL对等的规范中, 在友商家的卡上, 我们可以直接在启动kernel的时候, 提供这个坐标偏移量. 从而完成类似的操作, 而不需怎么改动代码. 所以你看, 这是一个相当实用的东西, 实用到友商家已经提供了API以方便你这样做了.

此外, 手册还提供了另外一个建议, 就是直接不要传输了, 直接就地使用. 因为zero-copy可以以一定的粒度, 直接从内存跨越PCI-E到L2(然后进一步到SM中). 这样根据手册这里的说法, 能在kernel的指令级别, 实现计算和传输的重叠. 但是根据我们的实践, 大部分的使用效果实际上并不好. 我们怀疑是可能是跨越PCI-E带来了更大更难掩盖的延迟或者其他因素, 这些需要等待确定. 但是手册中不强调的另外一个用法, 实际上效果非常好. 即将zero-copy作为容纳结果数据的, 写入的缓冲区. 这种可以将结果的回传, 和kernel的计算, 也在kernel的指令级别, 进行重叠. 而无需你事后开一个异步传输在某流中. 在我们的日常实践中, 这种具有非常好的使用效果. 好到了很多人都发现了这点. 并且在arvix上发文, 用FPGA拦截了zero-copy作为写入结果的缓冲区的时候, kernel的写入, 在指令级别的重叠, 通过L2, 跨越PCI-E回传的时候的情况, 并做了分析. 我们现在大致知道, 根据此文(我不记得番号了, 但是容易找到. 用FPGA + Zero-Copy的字样, 近期文章),

手册中的这种作为直接回写操作的做法, L2会产生跨越PCI-E的32B, 64B, 128B大小的传输的.

然后本文章还分析了, 为何只能达到约12GB/s, out of 16GB/s的原因(因为PCI-E的包大小的问题的浪费, 而不是编码问题). (注意这是说的PCI-E 3.0, 而不是4.0, 后者可能大约达到25GB/s, 这是根据我们客户的反馈, 而不是实际我们的测试).

大致是分析完了显存的特性、一个令人意外的(非常分散的不合并读写的优势)、 两种global memory中的前一种, 以及它的传输上的好用的地方, 和在Jetson上的应用。

cuda第一次计算耗时_CUDA优化的冷知识10 | GPU卡和Jetson上显存优化的特色相关推荐

  1. cuda合并访问的要求_CUDA优化的冷知识 5 | 似是而非的计时方法

    这一系列文章面向CUDA开发者来解读<CUDA C Best Practices Guide> (CUDA C最佳实践指南) 大家可以访问: https://docs.nvidia.com ...

  2. 显存优化 | Pytorch的显存机制torch.cuda.empty_cache及周边概念

    注:文中涉及一些内部底层实现机制,可能和大家外界看到的不一样,这里略过不做介绍.借着笔记,分享平时碰到的技术点,不高端,不炫酷,对你有用更好了. 最近在做模型的优化工作,主要涉及精度,速度和显存优化, ...

  3. tensorflow 显存 训练_【他山之石】训练时显存优化技术——OP合并与gradient checkpoint...

    作者:bindog 地址:http://bindog.github.io/ 01 背景 前几天看到知乎上的文章FLOPs与模型推理速度[1],文中提到一个比较耗时又占显存的pointwise操作x * ...

  4. MegEngine亚线性显存优化

    MegEngine亚线性显存优化 MegEngine经过工程扩展和优化,发展出一套行之有效的加强版亚线性显存优化技术,既可在计算存储资源受限的条件下,轻松训练更深的模型,又可使用更大batch siz ...

  5. 深度解析MegEngine亚线性显存优化技术

    基于梯度检查点的亚线性显存优化方法[1]由于较高的计算/显存性价比受到关注.MegEngine经过工程扩展和优化,发展出一套行之有效的加强版亚线性显存优化技术,既可在计算存储资源受限的条件下,轻松训练 ...

  6. 深度学习分布式策略优化、显存优化、通信优化、编译优化综述

    综述 因为我个人最近在从事可能是AI领域对性能挑战最大的方向,自动驾驶领域,所以对整个深度学习训练的优化尤为关注,最近一直在学习相关内容,谨以此篇文章做一个总结. 我一直很看好深度学习训练优化这个方向 ...

  7. 深度学习 占用gpu内存 使用率为0_深度解析MegEngine亚线性显存优化技术

    作者 | 旷视研究院 编辑 | Linda 基于梯度检查点的亚线性显存优化方法 [1] 由于较高的计算 / 显存性价比受到关注.MegEngine 经过工程扩展和优化,发展出一套行之有效的加强版亚线性 ...

  8. 显存优化:纹理压缩功能介绍与使用说明

    由于近期在开发者群里发现一些开发者对纹理压缩不太理解,遇到一些使用上的问题,所以本次文章中对纹理压缩进行详细的说明和使用上的介绍,希望能对有需求的开发者带来帮助. 本篇文章已经先更新到官网的文档中,也 ...

  9. 阿里 NIPS 2017 Workshop 论文:基于 TensorFlow 的深度模型训练 GPU 显存优化

    NIPS 2017 在美国长滩举办,场面非常热烈.阿里巴巴一篇介绍深度模型训练 GPU 显存优化的论文<Training Deeper Models by GPU Memory Optimiza ...

最新文章

  1. 多采样率信号处理 ——信号的抽取与插值
  2. python请用自定义函数实现账号密码的输入_Python实现控制台输入密码的方法
  3. python os模块是什么_python常见模块之os模块
  4. 信用差价Definition of 'Credit Spread'
  5. 索尼服务器维护时间,索尼云服务器
  6. 三星java3倍拍照手机_全世界拍照最强的两款手机,一个是三星,一个是它
  7. MobileNet V2简单总结
  8. 管天管地管空气!谷歌探索用CV估算空气质量
  9. java 原子数据类型_java并发编程(十一)----(JUC原子类)基本类型介绍
  10. as3.0横向渐变发光字
  11. jest单元测试-更多
  12. 3803. 数组去重-AcWing题库
  13. codesmith for java_codesmith 入门介绍【转载】
  14. Istio和Linkerd基准性能测试对比
  15. 基础项目-家庭记录收支程序
  16. 老郑学长 | 天津师范大学体育硕士怎么样
  17. 7-44 [0508]个人所得税
  18. 英文学习20171221
  19. 1-计算机系统概述(CO)
  20. 2022山东艾灸展,济南中医艾灸展,艾制品展,中国艾灸仪器展

热门文章

  1. 程序员到底该怎么给女朋友挑礼物
  2. 2019数据安装勾选_万能的XY数据标签插件,柱形图也可以呈现变化率
  3. 计算机科学导论实验考试,计算机科学导论实验指导书
  4. CodeForces 906D (欧拉降幂)
  5. python基础之---03基本语法
  6. HelloMyBLOG!!!
  7. C++ map嵌套使用 链接
  8. web默认字体最佳实践
  9. 如何在win2003下安装sql2008[多次安装sql2008失败者必看]
  10. SQL2005 BI系列课程