DAY30:阅读CPU与GPU之间的数据传输

我们正带领大家开始阅读英文的《CUDA C Programming Guide》,今天是第30天,我们正在讲解性能,希望在接下来的60天里,您可以学习到原汁原味的CUDA,同时能养成英文阅读的习惯。

本文共计273字,阅读时间15分钟

5.3.1. Data Transfer between Host and Device

Applications should strive to minimize data transfer between the host and the device. One way to accomplish this is to move more code from the host to the device, even if that means running kernels with low parallelism computations. Intermediate data structures may be created in device memory, operated on by the device, and destroyed without ever being mapped by the host or copied to host memory.

Also, because of the overhead associated with each transfer, batching many small transfers into a single large transfer always performs better than making each transfer separately.

On systems with a front-side bus, higher performance for data transfers between host and device is achieved by using page-locked host memory as described in Page-Locked Host Memory.

In addition, when using mapped page-locked memory (Mapped Memory), there is no need to allocate any device memory and explicitly copy data between device and host memory. Data transfers are implicitly performed each time the kernel accesses the mapped memory. For maximum performance, these memory accesses must be coalesced as with accesses to global memory (see Device Memory Accesses). Assuming that they are and that the mapped memory is read or written only once, using mapped page-locked memory instead of explicit copies between device and host memory can be a win for performance.

On integrated systems where device memory and host memory are physically the same, any copy between host and device memory is superfluous and mapped page-locked memory should be used instead. Applications may query a device is integrated by checking that the integrated device property (see Device Enumeration) is equal to 1.

本文备注/经验分享:

这章节主要说了如何优化Host和Device间的数据传输。

首先章节说, 应当尽量尝试能减少传输量就要减少,例如一段数据如果原本需要从显存移动到内存, 然后CPU继续处理;那么如果通过代码改写, 将一些CPU上的代码改写成GPU版本, 这样就可以不用移动这些数据了, 直接就能在GPU上处理了。有的时候虽然这种改写可能很渣,并行度不高, 但只要是合算的, 就应当使用这种GPU代码,也就是说, 就算是渣GPU代码, 运行的时间能小于数据移动的时间,那么即使改写成GPU不是那么的好, 也要改写成GPU版本。 这是一个很重要的思路. 有很多人认为我这段代码太串行了, 并行度不高, 还是不改写了。但是这里指出, 最好还是改写, 虽然是在不适合GPU的情况下运行, 但只要总体成本合算,还是要改写的,因为相比现在的GPU上的计算性能和GPU上的访存性能,PCI-E传输的性能太低了。通过这种改写,可能在GPU上, 最终处理得到一个很小的数据(例如, 一张被处理过的图片被识别为99%是狗), 那么只将最终的结果"狗"返回即可,其他的中间数据均可以在GPU上就地不要了。这样通过尽量在GPU上能处理的都处理了, 实在最后的非常小的数据量再返回, 有利提高性能。 第二段则说了, 如果你有一大批传输, 每次传输都很小(例如1000个只有100KB的的小图像), 与其传输1000次小的,不如打包成一次大的传输(100MB的100KB的小图像打包),因为每次传输有基本的不能避免的开销, 这样打包后一次传输较大的, 有利于提高性能(固定的每次传输的代价, 例如对GPU的DMA引擎进行设定, 提供起始地址, 目标地址, 传输大小什么. 等等,再例如固定的代价有在WDDM上切换到kernel-mode等等),所以一次传输大数据量, 而不是多次小的, 也有利于提高性能. 第三段实际上有点小问题.他说使用page-locked memory在古老的FSB总线的机器上能提高性能.这个实际上几乎能在现在所有的机器上都提高性能.包括AMD的U和板子.这是因为: (1)普通的传输(cudaMemcpy)会在内存中进行staging, 浪费内存读写带宽. (2)普通的传输往往会导致使用默认流, 造成用户不自觉的在device上的隐式同步, 浪费性能.(3)普通的传输往往会导致Host被阻塞等待, 浪费性能。 因此这里实际上所有的机器上使用page-locked memory传输都是很好的. 而不仅仅是10年前的FSB总线的机器。 但需要注意的是, 不要过量分配page-locked memory, 特别是小内存的机器(例如只有16GB内存的机器), 避免系统内存不够用. 影响其他方面的性能。 此外, 这里还说了, 如果对于那种只用一次的数据,例如一个kernel只对一张图片读取1次, 那么不需要手工传输, 直接使用映射的page-locked memory即可(也叫zero-copy), 有如下好处: (1)用户不需要手工准备一份设备上的对应大小的缓冲区, 节省了显存; (2)用户不需要提前复制完数据才能启动kernel. 可以在kernel一边执行的同时, 一边自动从PCI-E传输过来. 这样kernel的计算指令实际上能和PCI-E传输overlap, 节省时间; 但也需要注意的是, 使用多次的数据不应当这样. 而需要提前复制过来, 因为多次读写显存更具有优势。除此之外,在Linux下, 应当考虑使用unified memory, Pascal+在Linux下使用unified memory具有更好的性能. 而且在一定的情况下, 可以适应多次使用的数据.但在Windows下面不建议使用(因为Windows下面的Unified memory性能很低),Linux下的unified memory可以看成是zero-copy这里的高级版本,进化过了。

最后章节还说了集成显卡的优化。对于那种集成在笔记本中之类的集成显卡,很多是没有独立显存的,此时他们的显存就是内存(映射的),此时应当就地直接使用映射的内存, 而不需要cudaMemcpy复制.因为并没有一个独立的显存存在. 只有内存. 复制的话实际上是你在内存中倒腾。 因为实际上现在的的映射的内存(zero-copy)总是有更高的高级版本unified memory, 在这种设备上应当条件允许就使用unified memory(linux),不允许就普通映射,但不应当手工复制。 这种设备通过查询"集成"属性, 值是1; 我补充一下: (1)这种显卡已经消失了很多年了. 现在即使是笔记本中的集成显卡, 也有独立显存的.所以手册这里的说法是没有用的了. 它没有更新. (2)现在多了TK1/TX1/TX2这种设备, 他们的GPU也是集成的, 也没有独立的显存.在这种设备上应当考虑使用zero-copy/unified memory以便减少无辜的复制传输(根本显卡就没有走PCI-E好么!),以便提高性能。 总之本章节说, 能不传输就不传输, 例如对于可以改变数据处理代码的位置(从CPU到GPU); 或者不需要传输(集成或者TX2类的)就应当尽量不需要传输.然后还说了, 如果真的要传输, 尽量使用一次性大量传输, 尽量使用page-locked memory。 本章节还说了, 有的时候可以让kernel执行和数据传输在指令级overlap提高性能, 适合那些只读一次或者只写一次的数据(或者例如最终结果的回传, 可以直接集成在kernel中, 让kernel直接写内存).

有不明白的地方,请在本文后留言

或者在我们的技术论坛bbs.gpuworld.cn上发帖

原文发布于微信公众号 - 吉浦迅科技(gpusolution)

原文发表时间:2018-06-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏施炯的IoT开发专栏

Endnote for Windows Mobile

  想必园子里有好多朋友都写过paper吧,在阅读文献的时候,是不是觉得管理文献这个事情很麻烦。我正处于刚刚起步的阶段,英语写译老师Greatlion给我们推荐...

1986
来自专栏IT派

从零开始:手把手教你安装深度学习操作系统、驱动和各种python库!

为了研究强化学习,最近购置了一台基于 Ubuntu 和英伟达 GPU 的深度学习机器。尽管目前在网络中能找到一些环境部署指南,但目前仍然没有全面的安装说明。另外...

4248
来自专栏吉浦迅科技

放下王者农药这锅,玩一把Tensorflow吧

暑期开始了!对于Lady姐来说,如何安排儿子的暑期生活是一件大事,显然是不能沉迷于王者农药, ? 于是Lady姐随手扔了一个教程给他:按照这份教程,在家里Win...

38910
来自专栏简书专栏

视频压缩工具ffmpeg的使用

这篇文章中的视频压缩非常适用于教学视频的压缩,因为教学视频中很多帧数的内容都是相同的。 本文作者的CPU是E5-2670,8核16线程。视频压缩工具ffmpe...

9155
来自专栏CSDN技术头条

详解 NoSQL 数据库的分布式算法

系统的可扩展性是推动NoSQL运动发展的的主要理由,包含了分布式系统协调,故障转移,资源管理和许多其他特性。这么讲使得NoSQL听起来像是一个大筐,什么都能塞进...

2209
来自专栏吉浦迅科技

Unified Memory

首先讲一下Unified Memory(统一内存寻址)。在编写CUDA程序的时候,我们需要在CPU端和GPU端分别定义不同的内存空间,用于存储输入或输出的数据。...

32510
来自专栏AI研习社

用GPU加速深度学习: Windows安装CUDA+TensorFlow教程

背景 在Windows上使用GPU进行深度学习一直都不是主流,我们一般都首选Linux作为深度学习操作系统。但很多朋友如果只是想要了解深度学习,似乎没有必要...

9424
来自专栏吴伟祥

MySQL基准测试 转

基准测试是  指通过设计科学的测试方法、测试工具和测试系统,实现对一类测试对象的某项性能指标进行定量的和可对比的测试。例如,对计算机CPU进行浮点运算、数据访问...

1213
来自专栏iOSDevLog

Google Colab免费GPU教程

现在,你可以开发深度学习与应用谷歌Colaboratory -on的免费特斯拉K80 GPU -使用Keras,Tensorflow和PyTorch。

3785
来自专栏沈唁志

如何简单计算PHP网站是否已经最高负载

2005

扫码关注云+社区