4

我正在尝试使用 VS 2010 的 Parallel Nsight 2.1 版本来优化我的 CUDA 程序。

我的程序在带有 GTX 480 板的 Windows 7(32 位)机器上运行。我已经安装了 CUDA 4.1 32 位工具包和 301.32 驱动程序。

程序中的一个周期包括将主机数据复制到设备、执行内核以及将结果从设备复制到主机。

正如您在下面的分析器结果图片中看到的那样,内核在四个不同的流中运行。每个流中的内核依赖于“流 2”中复制到设备的数据。这就是为什么 asyncMemcpy 在不同流中启动内核之前与 CPU 同步的原因。

在此处输入图像描述

图片中让我恼火的是第一次内核启动结束(10.5778679285)和内核执行开始(10.5781500)之间的巨大差距。启动内核大约需要 300 我们,这在不到 1 毫秒的处理周期中是一个巨大的开销。

此外,内核执行和将结果的数据复制回主机没有重叠,这进一步增加了开销。

这种行为有什么明显的原因吗?

4

1 回答 1

6

我可以通过跟踪来判断三个问题。

  1. Nsight CUDA 分析每次 API 调用增加约 1 µs。您同时启用了 CUDA 运行时和 CUDA 驱动程序 API 跟踪。如果您要禁用 CUDA 运行时跟踪,我猜您会将宽度减小 50 µs。

  2. 由于您在 Windows 7 上使用 GTX 480,因此您在 WDDM 驱动程序模型上执行。在 WDDM 上,驱动程序必须进行内核调用才能提交工作,这会带来很多开销。为了避免这种开销,CUDA 驱动程序在内部 SW 队列中缓冲请求,并在队列已满时将请求发送给驱动程序,它由同步调用刷新。您可以使用 cudaEventQuery 强制驱动程序刷新工作,但这可能会产生其他性能影响。

  3. 看来您正在以深度优先的方式将您的作品提交给流媒体。在计算能力 2.x 和 3.0 设备上,如果您以广度优先方式提交到流,您将获得更好的结果。在您的情况下,您可能会看到内核之间的重叠。

时间线屏幕截图没有为我提供足够的信息来确定为什么内存副本在所有内核完成后开始。给定 API 调用模式,您应该能够看到在每个流完成其启动后开始传输。

如果您正在等待所有流完成,则执行 cudaDeviceSynchronize 可能比 4 个 cudaStreamSynchronize 调用更快。

Nsight 的下一个版本将具有附加功能,以帮助理解 SW 队列以及将工作提交给计算引擎和内存复制引擎。

于 2012-08-30T16:15:05.193 回答