本章目标
- 了解如何分配和使用零拷贝内存(Zero-Copy Memory)
- 了解如何在同一个应用程序中使用多个GPU
- 了解如何分配和使用可移动的固定内存(Portable Pinned Memory)
零拷贝主机内存
固定内存(页锁定内存),这种新型的主机内存能够确保不会交换出物理内存.我们通过调用cudaHostAlloc()来分配这种主机内存,并且传递参数cudaHostAllocDefault来获得默认的固定内存.本章中,除了默认参数外,我们还可以传递cudaHostAllocMapped.它分配的固定内存除了有前边的属性外,还可以在CUDA C核函数中直接访问这种类型的主机内存.由于这种内存不需要复制到GPU,因此也成为零拷贝内存.
通过零拷贝内存实现点积运算
我们不需要将输入矢量显示复制到GPU,而是使用零拷贝内存从GPU中直接访问数据.
cudaHostAllocMapped标志告诉运行时将从GPU中访问这块内存.对于两个输入缓冲区,我们还指定了标志cudaHostAllocWriteCombined.这个标志表示,运行时应该将内存分配为合并式写入内存.此功能可以显著提升GPU读取内存时的性能.然而,当CPU也要读取这块内存时,就会很低效.
在使用标志分配好内存后,就可以从GPU中访问这块内存.然而,GPU的虚拟内存空间与CPU是不同的,因此在GPU上访问它们与CPU上访问它们有着不同的地址.调用cudaHostAlloc()将返回这块内存在CPU上的指针,因此需要调用cudaHostGetDevicePointer()来获得这块内存在GPU上的有效指针.
零拷贝内存的性能
对于集成GPU,使用零拷贝内存通常都会带来性能提升,因为内存在物理上是与主机共享的.将缓冲区声明为零拷贝内存的唯一目的就是避免不必要的数据复制.但是每个固定内存都会占用系统的可用物理内存,这最终会降低系统性能. 当输入内存和输出内存只使用一次时,那么在独立GPU上使用零拷贝内存将带来性能的提升.如果使用多次,直接将数据复制到GPU.