我一直在研究如何减少因CPU和GPU来回传输数据而导致的延迟。当我第一次开始使用CUDA时,我注意到CPU和GPU之间的数据传输确实需要几秒钟,但我并不在乎,因为这对我正在编写的小程序来说并不是一个真正的问题。事实上,对于绝大多数使用GPU,包括视频游戏的程序而言,延迟可能并不是一个大问题,因为它们仍然比在CPU上运行的速度快得多。
然而,我有点像HPC爱好者,当我看到天河一号理论峰值FLOPS与实际LINPACK测量性能之间存在巨大差异时,我开始关注我的研究方向。这引起了我对我是否采取正确的职业道路的担忧。
通过使用cudaHostAlloc()函数来使用固定内存(页面锁定)内存是一种减少延迟的方法(非常有效),但还有其他任何我不知道的技术吗?要说清楚,我说的是优化代码,而不是硬件本身(那是NVIDIA和AMD的工作)。
作为一个侧面问题,我知道戴尔和惠普销售的是特斯拉服务器。我很好奇GPU如何利用数据库应用程序,您需要从硬盘驱动器(HDD或SSD)中不断读取,这只是CPU可以执行的操作,
答案 0 :(得分:14)
有几种方法可以解决CPU-GPU通信开销问题 - 我希望你的意思是延迟,而不是传输本身的延迟。请注意,我故意使用术语地址而不是 reduce ,因为如果您可以隐藏它,则不一定需要减少延迟。另请注意,我对CUDA更熟悉,所以下面我只提到CUDA,但OpenCL也提供了一些功能。
正如您所提到的,页面锁定内存的目的是增加。此外,可以将页面锁定的主机内存映射到GPU,这种机制可以直接访问从GPU内核分配的数据,而无需额外的数据传输。这种机制称为零拷贝传输,如果数据仅在大量计算的情况下被读/写一次并且对于没有单独存储器(移动)的GPU而言是有用的。但是,如果访问零复制数据的内核不是强计算绑定的,因此无法隐藏数据访问的延迟,则页锁定但不映射的内存将更有效。此外,如果数据不适合GPU内存,则零拷贝仍然有效 请注意,过多的页面锁定内存会导致CPU端严重减速。
从tkerwin提到的不同角度解决问题,异步传输(CPU线程与GPU通信)是通过在CPU上重叠计算来隐藏CPU-GPU传输延迟的关键随着转移。这可以通过cudaMemcpyAsync()
实现,也可以使用异步内核执行的零拷贝实现
通过使用多个流与内核执行重叠传输,可以更进一步。请注意,流调度可能需要特别注意以实现良好的重叠; Tesla和Quadro卡具有双DMA引擎,可实现与GPU之间的同步数据传输。
此外,使用CUDA 4.0,从多个CPU线程中使用GPU变得更加容易,因此在多线程CPU代码中,每个线程都可以将自己的数据发送到GPU并更轻松地启动内核。
最后, GMAC 为CUDA实现了非对称共享内存模型。其中一个非常有趣的功能是它提供的一致性模型,特别是延迟和滚动更新,只能以阻塞的方式传输在CPU上修改的数据。 有关详细信息,请参阅以下文章:Gelado et al. - An Asymmetric Distributed Shared Memory Model for Heterogeneous Parallel Systems。
答案 1 :(得分:3)
您可以使用cudaMemcpyAsync()
重叠您在CPU上进行内存传输的工作。这不会降低数据传输的延迟,但可以提高算法的整体性能。 CUDA C Best Practices指南中提供了一些相关信息。
答案 2 :(得分:0)
如果延迟是个问题,那么可能需要考虑使用AMD融合架构可以做出的权衡。您获得的延迟极大地减少了,并且在某些情况下可能比CPU从RAM传输的速度更快。但是,使用精简的非离散GPU确实会降低性能。