浅谈CUDA零拷贝内存

今天看到有小伙伴提出了“零拷贝”的问题,由于本人以前用的也比较少,了解不多,因此打算好好研究一番,现做些总结。
        零拷贝内存是一种特殊形式的内存映射,它允许你将主机内存直接映射到GPU内存空间。因此,因此对GPU上的内存解引用时,如果是基于GPU的,那么就获得全局内存的高速带宽;如果GPU代码读取一个主机映射变量,它会提交一个PCI-E读取事务,主机会通过PCI-E总线返回数据。
        NVIDIA公司没有公布任何令拷贝内存实现的技术细节,只是针对如何使用做了阐述。那么零拷贝内存技术适用于什么情况下呢?
        1. 它适用于计算密集型的程序。如果计算密度够大,足够隐藏PCI-E传输延迟,那么线程束延迟隐藏模型同样可以用于PCI-E传输。它将计算与数据数据传输操作重叠了,无须显示的执行流管理。
        2. 程序一定要能够高效的利用数据。如果程序中多次读取或写入相同的数据,就会创建多个PCI-E传输事务。当然,如果在Fermi架构及以上的GPU中执行多次读取或多次写入,速度不会下降的很明显,因为Fermi架构引进了cache缓存技术,会从L1和L2级缓存中读取数据。

        具体的使用如下:
         开辟Host内存空间
C/C++ code
?
1
cudaHostAlloc(( void **)&host_data_to_device, size_in_bytes, cudaHostAllocMapped);

         获取Device端指针
C/C++ code
?
1
cudaHostGetDevicePointer(&dev_host_data_to_device, host_data_to_device, 0);

        获取了Host和Device端指针后,就可以同其它CUDA程序一样,操作数据了。在实际应用中,如果将数据和Kernel分割成更小的块,会得到更多执行与数据传输的重叠时间,从而降低整体的运行速度。再次提醒小伙伴们,零拷贝内存技术适用于计算密集型、读取写入次数少的程序中。


可以写个程序自己实现下,用上面提到过的API去申请一个超过GPU显存的内存空间,然后得到Device端的指针,进行操作,本人GPU的显存为6GB,内存32GB,实验中申请了16GB的空间,是可以申请下来的,而且执行Kernel操作的结果也是正确的

你可能感兴趣的:(浅谈CUDA零拷贝内存)