统一内存与固定主机内存的行为和性能

时间:2017-04-15 09:35:29

标签: memory optimization cuda gpgpu unified-memory

我是一名正在开展项目的学生,该项目包括在CUDA中编写某个程序。我相信这个计划的主题与这个问题无关;但我不得不提一下,我的教授建议我在看到我尝试创建CUDA智能指针类后,在我的程序中使用统一内存。最好将此类描述为“唯一指向数组的指针”,它满足RAII习语。

在检查了有关统一内存的CUDA 6.0发行说明(以及CUDA 8.0中引入的更新)之后,我完全怀疑是否应该切换到统一内存。

Q1:我知道CUDA统一内存正在映射GPU和CPU内存。但是我们在谈论什么样的CPU内存?固定内存是否允许更快的数据传输?或者它是标准的分页系统内存?

Q2:我知道CUDA 8.0中引入的更新主要是关于pascal架构的。但我可以期待Maxwell架构的加速(相对于主机固定内存)吗?

问题3:即使我只是一名学生,我也可以看到NVIDIA在开发统一内存方面投入了大量精力。因此,人们可能会认为从长远角度来看,使用统一内存是一个更好的主意。我是对的吗?

问题4:每次我想在主机上访问数组的单个元素(数据驻留在设备上)时,整个数组都会复制到主机吗?

1 个答案:

答案 0 :(得分:1)

GPU内存的智能指针

(部分)您的原始动机是使用智能指针(全局)GPU内存的可能性;并且你的教授建议为此采用统一记忆(虽然这对我来说并不完全清楚它会有什么帮助)。嗯,问题是,你不必重新发明轮子 - 你可以已经unique_ptr用于(不同类型的)CUDA GPU内存,作为{{{ 3}}库。

这些独特的指针实际上是std::unique_ptr(),但是使用自定义删除器(您可以使用适当的方法创建它们。您可以在cuda-api-wrappers找到创建它们的方法列表(尽管文档是此时非常偏袒)。

对于使用示例,请考虑CUDA示例示例this doxygen page,它执行两个向量的元素相加以生成第三个。 vectorAdd是相同的示例,使用智能指针同时为主机和设备内存(以及更常见的API包装器)。

警告:我是API包装器库的作者,所以我偏向于使用它: - )

(部分)回答您的具体问题

  

Q1:我们谈论的[统一内存分配]是什么样的CPU内存?它是固定内存......还是......标准分页系统内存?

我不知道,但您可以通过编写一个小程序轻松找到:

  1. 分配一些托管内存。
  2. 在主机端写入。
  3. 将其预取到GPU,然后退出。
  4. ...并对其进行分析以确定PCIe带宽。使用PCIe 3.0并且没有中间流量,我通常从固定内存中获得~12 GB /秒,而从未固定内存获得约一半。

      

    Q2:...在CUDA 8.0中...我能指望Maxwell架构加速(相对于主机固定内存)吗?

    在我非常有限的经验中,相对于CUDA 6.0,CUDA 8.0中统一内存访问卡的性能没有提高。 (但是在预取逻辑或通用代码优化方面可能存在引擎盖下的变化,在某些情况下确实显示出改进。)无论如何,请记住CUDA 6.0不支持sm_52目标,所以你的问题有点没有实际意义

      第三季:......我可以看到NVIDIA在开发统一内存方面付出了很多努力。因此,人们可能会认为从长远角度来看,使用统一内存是一个更好的主意。我是对的吗?

    我相信你错了。正如CUDA编程指南所建议的那样,统一存储器是一种旨在简单地存储访问和编程的机制;它为了更均匀,更简单的代码而牺牲了一些速度。虽然nVIDIA的努力可能会减少使用它的开销,但没有疯狂的优化冲刺会让它消失。关于Kepler Tesla,Here各种基准测试;虽然我没有Maxwell或Pascal的数据,但我怀疑这会让你更喜欢全面使用统一内存。

      第四季:每次我想在主机上访问数组的单个元素(数据驻留在设备上)时,整个数组都会被复制到主机吗?

    不,托管内存被分页;因此,只能在PCIe总线上复制一个页面。但是如果数组很小,它可能就是整个数组。