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 条评论
登录 后参与评论

相关文章

来自专栏腾讯云serverless的专栏

使用 Serverless 进行 AI 预测推理

本文演示如何使用腾讯云的 SCF 无服务器云函数来实现 AI Serving 能力。

2.8K60
来自专栏性能与架构

Nginx的I/O性能为什么比Apache更高效?

Nginx与Apache的I/O性能差距源于他们采用不同的I/O模型 Apache - select模型 Nginx - epoll模型 特点对比 se...

33710
来自专栏AILearning

TensorFlow架构

我们设计了TensorFlow进行大规模的分布式训练和推理,但它也足够灵活,以支持新机器学习模型和系统级优化的实验。 本文档描述了使得这种组合规模和灵活性成...

3457
来自专栏影子

一张图解析 编译器编译流程

35915
来自专栏拂晓风起

【转】Flash:同志们,这些知识点你们知道多少?(一些必备的Flash开发知识点)

882
来自专栏乐沙弥的世界

Oracle AWR特性描述

AWR是Automatic Workload Repository的简称,中文叫着自动工作量资料档案库。既然是仓库,又是保存负载数据,所以保存的是数据库性能相关...

571
来自专栏SDNLAB

基于跳数\\时延\\带宽的最短/优路径和负载均衡

对于SDN初学者而言,最短路径转发应用和负载均衡应用是最常见,也是最适合学习的经典应用。根据链路权重参数的不同,主要有基于跳数、时延和带宽的几种最短\最优路径转...

37416
来自专栏鸿的学习笔记

如何设计一个良好的流系统?(上)

streaming system有两篇经典博客:streaming 101和streaming 102,深刻的描述了流系统的精髓和对未来的展望,这篇文章权当一个...

521
来自专栏PaddlePaddle

PaddlePaddle发布v0.10.0版

我们非常高兴发布了PaddlePaddle V0.10.0版,并开放了新的Python API。 之前在v0.9.0版,完成一个训练或预测任务至少需要两份pyt...

3497
来自专栏微服务生态

SEDA架构模型

特点:每任务一线程直线式的编程使用资源昂高,context切换代价高,竞争锁昂贵太多线程可能导致吞吐量下降,响应时间暴涨。

913

扫码关注云+社区