【问题标题】:cudaEventRecord() Does not time correctly on Visual Studio CPU codecudaEventRecord() 在 Visual Studio CPU 代码上的时间不正确
【发布时间】:2015-09-11 19:30:14
【问题描述】:

在做一些由 NVIDIA 制作的 CUDA 基本示例时,我复制了一些代码来测试从 CPU 到 GPU 计算的矩阵乘法加速。

查看结果 30 分钟后,看到我的 CPU(是的 CPU)的计算速度比我的 GPU 快 1000 倍,我意识到计时工作不正确。代码片段如下(这是来自 NVIDIA 的代码):

//Create timers
cudaEvent_t start;
cudaEvent_t stop;
float simpleKernelTime;
float optimisedKernelTime;

//start timer
cudaEventCreate(&start);
cudaEventCreate(&stop);
cudaEventRecord(start, 0);

matrixMultKernel<<<grid, block >>>(a_d, b_d, c_d, N);

cudaEventRecord(stop, 0);
cudaEventSynchronize(stop);
cudaEventElapsedTime(&elapsedTime, start, stop);

// Print time and do other things

cudaEventRecord(start, 0);

matrixMultCPU(a_h, b_h, d_, N);

cudaEventRecord(stop, 0)
cudaEventSynchronize(stop);
cudaEventElapsedTime(&elapsedTime, start, stop);

// Print time

这段代码在 Linux 机器上运行良好(我复制了与我旁边的人相同的代码,他得到了很好的时机)但在装有 Visual Studio 2013 的 Windows 8 机器上,CPU 部分的时间(下半场)剪断的)不起作用(总是给出〜0.003ms)。

为什么会发生这种情况?我使用&lt;time.h&gt; 修复了它(删除cudaEventRecord() 调用并使用标准C 代码计时方法),所以我不想知道如何修复它,但更多的是为什么会发生这种情况。

【问题讨论】:

  • @buttifulbuttefly nononono,我删除了 cudaEventRecord 调用并使用标准 C 时序。
  • 关于近距离投票:“这段代码正在工作,我知道如何让它正常工作。我不是在寻求代码调试帮助,这是一个很好的理论问题,我相信。
  • 在 Linux 和 Windows 上,TCC 驱动程序工作直接从驱动程序提交到 GPU 推送缓冲区。在 Windows 上,WDDM 驱动程序工作被提交到软件队列中。当此溢出时,工作将在命​​令缓冲区中提交给 WDDM 内核模式驱动程序,并且驱动程序将完整的命令缓冲区提交给 GPU。如果您在 cudaEventRecord(start...) 之后添加调用 cudaEventQuery(0),您应该会看到更接近 Linux 的行为,因为这将刷新队列。也就是说,不要使用 cudaEventRecord 或时钟来计时 CPU 时钟。使用平台高精度计时器。

标签: c windows visual-studio-2013 time cuda


【解决方案1】:

据我了解,CUDA 事件本身并非旨在测量仅 CPU(仅主机)时间,而是用于测量内核执行和 CUDA API 调用。来自CUDA C Programming Guide3.2.5.6. 事件(强调我的):

运行时还提供了一种密切监视设备的 进度,以及执行准确的计时,通过让 应用程序在程序中的任何点异步记录事件 并查询这些事件何时完成。

我也很惊讶您可以随时获得(内核启动是异步的),因为您的代码丢失了cudaEventSynchronize()

cudaEventRecord(stop, 0);
cudaEventSynchronize(stop);
cudaEventElapsedTime(&elapsedTime, start, stop);

另见How to Implement Performance Metrics in CUDA C/C++

对于仅 CPU 时间测量,请参阅 this thread

编辑:

要获得matrixMultCPU() 的正确时间,您需要为start 事件添加同步:

cudaEventRecord(start, 0);
cudaEventSynchronize(start);

【讨论】:

  • 哎呀,我的错!我在原始代码中确实使用了cudaEventSynchronize(stop);。但是,cudaEventRecord() 在其他系统/编译器的 CPU 上工作(不知道为什么)。我的意思是,代码是由 NVIDIA 编写的,而不是我,我在其他操作系统/编译器中看到它的正确时间,只是无法在我的系统上运行。
  • 也许我的问题正好相反:为什么cudaEventRecord() 使用nvcc 在Linux 上为非GPU 代码计时工作?
  • @AnderBiguri:我编辑了我的答案。看看这是否适合你。可能 GNU/Linux 实现会隐式同步 start
  • 我明白了,谢谢。我将把它打开一段时间,因为我对为什么会发生这种情况很感兴趣。
猜你喜欢
  • 2021-08-22
  • 2020-07-25
  • 1970-01-01
  • 1970-01-01
  • 2020-01-21
  • 2017-11-09
  • 1970-01-01
  • 2016-12-19
  • 1970-01-01
相关资源
最近更新 更多