4

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

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

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

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

Q3:虽然我只是一个学生,但我可以看到英伟达在开发统一内存方面投入了大量的工作。因此,从长远来看,人们可能会认为使用统一内存是一个更好的主意。我对吗?

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

4

1 回答 1

2

GPU 内存的智能指针

(部分)您最初的动机是为(全局)GPU 内存使用智能指针的可能性;并且您的教授建议为此使用统一记忆(尽管我并不完全清楚这将有何帮助)。好吧,问题是,您不必为此重新发明轮子 -unique_ptr作为cuda-api-wrappers库的一部分,您已经可以拥有(不同种类的)CUDA GPU 内存。

这些唯一的指针实际上是std::unique_ptr(),但是使用自定义删除器(并且您使用适当的方法创建它们。您可以在此 doxygen 页面上找到用于创建它们的方法列表(尽管此时文档非常部分)。

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

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

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

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

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

  1. 分配一些托管内存。
  2. 在主机端写入它。
  3. 将其预取到 GPU,然后退出。

...并对其进行分析以确定 PCIe 带宽。使用 PCIe 3.0 并且没有干预流量,我通常从固定内存获得约 12 GB/秒,从未固定内存获得大约一半。

Q2:……在 CUDA 8.0 中……我可以期待 Maxwell 架构的加速(相对于主机固定内存)吗?

在我非常有限的经验中,统一内存访问卡的性能在 CUDA 8.0 中相对于 CUDA 6.0 并没有提高。(但在某些情况下,预取逻辑或一般代码优化可能会有所改进。)无论如何,请记住 CUDA 6.0 不支持 sm_52 目标,因此您的问题有点没有实际意义。

Q3:...我可以看到英伟达在开发统一内存方面投入了大量工作。因此,从长远来看,人们可能会认为使用统一内存是一个更好的主意。我对吗?

我相信你错了。正如 CUDA 编程指南所建议的,统一内存是一种旨在简化内存访问和编程的机制。它牺牲了一些速度以获得更统一、更简单的代码。虽然 nVIDIA 的努力可能会在一定程度上减少使用它的开销,但没有疯狂的优化破折号可以让这种情况消失。在 Kepler Tesla 上,在各种基准测试中,使用统一内存通常会慢 1.8-2 倍;即使我没有 Maxwell 或 Pascal 的数据,我怀疑这会下降太多,以至于让您更喜欢全面使用统一内存。

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

不,托管内存是分页的;所以只有一个页面会通过 PCIe 总线被复制。但如果数组很小,它可能是整个数组。

于 2017-04-16T09:17:41.460 回答