Cuda锁页内存和零复制

Pre

为了对某一数据集进行操作,你需要将数据从主机传输到设备上、在数据集上进行操作,然后将结果传输回主机。由于是在完全串行的方式下执行的,这将导致主机和设备在一段时间内都是闲置的,白白浪费了传输能力和计算能力。本文介绍了锁页内存(Pinned Memory/PageLocked Memory)和零复制(Zero Copy)来节省甚至去掉数据传输耗费。

锁页内存(Pinned Memory/PageLocked Memory)

主机处理器支持虚拟内存系统,其中物理内存也可以标记为换出状态,然后将它更换到磁盘上,一旦需要该页了,则重新加载回来。允许程序员使用比实际空间更大的虚拟地址空间。

可以认为虚拟内存是内存容量受限留下的后遗症。

锁页内存允许GPU上的DMA控制器请求主机传输而不需要CPU主机处理器的参与。

在GPU上分配的内存默认都是锁页内存,这只是因为GPU不支持将内存交换到磁盘上。

分配锁页内存

在主机上分配锁页内存,使用特殊的cudaHostMalloc函数或者使用常规的malloc函数然后将其注册为锁页内存。

注册内存只是设置一些内部标志以确保内存从不被换出,并告诉CUDA驱动程序,该内存为锁页内存,能直接使用它而不需要使用临时缓冲区。

释放锁页内存

如果使用cudaHostAlloc,则需要使用cudaFreeHost函数释放这一块内存。不要调用常规的C语言函数释放,否则可能会崩溃或者出现一些不常见的错误。

函数原型

cudaHostAlloc函数的原型是:

cudaError_t cudaHostAlloc(void ** host_pointer,size_t size,unsigned int flags)

特点

然而分页锁定主机存储器是稀缺资源,所以可分页内存分配得多的话,分配会失败。另外由于减少了系统可分页的物理存储器数量,分配太多的分页锁定内存会降低系统的整体性能

使用分页锁定内存,分页锁定内存和显存之间的拷贝速度大约是6GB/s,普通的分页内存和GPU间的速度大约是3GB/s,(另外:GPU内存间速度是30G,CPU间内存速度是10GB/s),但是这种方法会带来额外的cpu内存间的拷贝时间(因为cpu需要把数据从可分页内存先拷贝到分页锁定内存)

而通过函数cudaHostRegister()把普通内存改为分页锁定内存,则不会带来额外的cpu内存拷贝时间,实验证明该方法有效果。

零复制(Zero Copy)

零复制是一种特殊形式的内存映射,它允许你将主机内存直接映射到GPU内存空间上。因此,当你对GPU上的内存解引用时,如果它是基于GPU的,那么你就获得了全局内存的高速带宽(180GB/s)。如果GPU代码读取一个主机映射变量,它会提交一个PCI-E读取事务,很长时间之后,主机会通过PCI-E总线返回数据。

如果程序是计算密集型,那么零复制可能是一项非常有用的技术。它节省了设备显示传输的时间。事实上,是将计算和数据传输操作重叠了,而且无需执行显式的内存管理。

实际上,使用零复制内存,将传输和内核操作分成更小的块,然后以流水线的方式执行它们。

然而,采用零复制内存的传输实际上是相当小的。PCI-E总线在两个方向上的带宽的欧式相同的。由于基于PCI-E的内存读取存在高延迟,因此实际上大多数读操作应该在所有写操作之前被放入读队列。我们可能获得比显式内存复制版本节省大量执行时间的效果。

Reference

http://blog.csdn.net/caoeryingzi/article/details/21323475

http://blog.csdn.net/zhangpinghao/article/details/21046435?utm_source=tuicool

文章版权归 FindHao 所有丨本站默认采用CC-BY-NC-SA 4.0协议进行授权|
转载必须包含本声明,并以超链接形式注明作者 FindHao 和本文原始地址:
https://www.findhao.net/easycoding/1349

你可能喜欢:(相似内容推荐和广告都使用了谷歌的推荐系统,需要对本站取消广告屏蔽才能显示。感谢点击↓广告支持博主~)

Find

新浪微博(FindSpace博客)QQ群:不安分的Coder(375670127) 不安分的Coder

2 条回复

  1. 李纪超说道:

    我认为“可以认为虚拟内存是内存容量受限留下的后遗症”有误:
    虚拟内存的作用不仅仅是让磁盘为内存充当缓存,还有简化链接、管理内存访问权限、实现进程间资源隔离的作用。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*