【问题标题】:CUDA Zero Copy memory considerationsCUDA 零拷贝内存注意事项
【发布时间】:2011-06-27 19:29:03
【问题描述】:

我正在尝试确定使用 cudaHostAlloc(或 cudaMallocHost?)是否合适。

我正在尝试运行一个内核,其中我的输入数据超过了 GPU 上的可用数据量。

我可以 cudaMallocHost 比 GPU 上更多的空间吗?如果没有,假设我分配了 1/4 我需要的空间(这将适合 GPU),使用固定内存有什么好处吗?

我基本上仍然必须从那个 1/4 大小的缓冲区复制到我的完整大小的 malloc'd 缓冲区中,这可能并不比仅使用普通 cudaMalloc 快吗?

这种典型的使用场景是否适合使用 cudaMallocHost:

  1. 分配固定的主机内存(我们称之为“h_p”)
  2. 用输入数据填充 h_p-
  3. 在 GPU 上为 h_p 获取设备指针
  4. 使用该设备指针运行内核来修改数组的内容-
  5. 像平常一样使用 h_p,现在已经修改了内容-

所以 - 在第 4 步和第 5 步之间没有任何副本可以满足,对吧?

如果这是正确的,那么我可以看到至少一次适合 GPU 的内核的优势

【问题讨论】:

  • 你似乎在问几个问题......
  • @Derek 为了避免在带有cudaHostAlloc() 的主机中使用不可分页内存(也称为固定内存)时出现副本,您只需使用标志cudaHostAllocMapped 而不是cudaHostAllocDefault分配时。通过这种方式,您可以直接从 CUDA C 内核中访问主机内存。这被称为zero-copy memory。固定内存也像一把双刃剑,运行应用程序的计算机需要为每个页面锁定缓冲区提供可用的物理内存,因为这些缓冲区永远无法换出到磁盘,但这会导致更快的内存耗尽。跨度>

标签: c++ cuda


【解决方案1】:

还可以考虑使用流进行重叠数据传输/内核执行。 这为数据块提供了 gpu 工作

【讨论】:

    【解决方案2】:

    就 CUDA 应用程序的性能而言,内存传输是一个重要因素。 cudaMallocHost 可以做两件事:

    • 分配固定内存:这是 CUDA 运行时可以跟踪的页面锁定主机内存。如果以这种方式分配的主机内存作为源或目标包含在 cudaMemcpy 中,则 CUDA 运行时将能够执行优化的内存传输。
    • 分配映射内存:这也是页锁定内存,可以直接在内核代码中使用,因为它被映射到 CUDA 地址空间。为此,您必须在使用任何其他 CUDA 函数之前使用cudaSetDeviceFlags 设置cudaDeviceMapHost 标志。 GPU 内存大小不限制映射主机内存的大小。

    我不确定后一种技术的性能。它可以让你很好地重叠计算和通信。

    如果您在内核中以块的形式访问内存(即您不需要整个数据,而只需要一个部分),您可以使用多缓冲方法,通过启用多个缓冲区来利用 cudaMemcpyAsync 的异步内存传输GPU:在一个缓冲区上计算,将一个缓冲区传输到主机,同时将一个缓冲区传输到设备。

    我相信您在使用cudaDeviceMapHost 分配类型时关于使用场景的断言是正确的。您不必进行显式复制,但肯定会有您看不到的隐式复制。它有可能与您的计算很好地重叠。请注意,您可能需要同步内核调用以确保内核已完成并且您在 h_p 中有修改后的内容。

    【讨论】:

      【解决方案3】:
      1. 是的,您可以 cudaMallocHost 比 gpu 上更多的空间。
      2. 固定内存可以有更高的带宽,但会降低主机性能。在普通主机内存、固定内存、写组合内存甚至映射(零拷贝)内存之间切换非常容易。为什么不先使用普通主机内存,对比一下性能?
      3. 是的,您的使用场景应该可以工作。

      请记住,全局设备内存访问速度很慢,零拷贝主机内存访问速度更慢。零拷贝是否适合你完全取决于你如何使用内存。

      【讨论】:

        【解决方案4】:

        CUDA C 编程指南和 CUDA 最佳实践指南都没有提到 cudaMallocHost 分配的数量't不能大于设备内存,所以我认为这是可能的。

        从页面锁定内存到设备的数据传输比普通数据传输更快,如果使用写组合内存,甚至更快。 此外,以这种方式分配的内存可以映射到设备内存空间,从而完全无需(手动)复制数据。它会在需要数据时自动发生,因此您应该能够处理比设备内存容量更多的数据。

        但是,如果页面锁定量占主机内存的很大一部分,(主机的)系统性能可能会受到很大影响。

        那么什么时候使用这种技术呢?很简单:如果数据需要只读一次,只写一次,就使用它。它将产生性能提升,因为无论如何都必须在某些时候来回复制数据。但是,一旦需要存储不适合寄存器或共享内存的中间结果,请使用 cudaMalloc 处理适合设备内存的数据块。

        【讨论】:

          【解决方案5】:

          使用主机内存会比设备内存慢几个数量级。它具有非常高延迟和非常有限吞吐量。例如,当 GTX460 上的设备内存带宽为 108GB/s 时,PCIe x16 的容量仅为 8GB/s

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-06-13
            • 1970-01-01
            • 1970-01-01
            • 2012-06-05
            • 2016-08-14
            • 1970-01-01
            • 2020-01-05
            • 2012-09-11
            相关资源
            最近更新 更多