什么时候调用cudaDeviceSynchronize?

use*_*226 53 cuda gpu gpgpu

什么时候cudaDeviceSynchronize真的需要调用这个函数?

据我从CUDA文档中了解,CUDA内核是异步的,因此我们应该cudaDeviceSynchronize在每次内核启动后调用它们.但是,cudaDeviceSynchronize在时间测量之前,除了一个之外,我尝试了相同的代码(训练神经网络).我发现我得到了相同的结果,但速度在7-12x之间(取决于矩阵大小).

所以,问题是是否有任何理由使用cudaDeviceSynchronize时间测量.

例如:

我应该放在cudaDeviceSynchronize两者之间吗?

从我的实验看来我没有.

为什么这么cudaDeviceSynchronize慢的程序呢?

ala*_*and 54

虽然CUDA内核启动是异步的,但是所有与GPU相关的任务都放在一个流中(这是默认行为)是按顺序执行的.

所以,例如,

kernel1<<<X,Y>>>(...); // kernel start execution, CPU continues to next statement
kernel2<<<X,Y>>>(...); // kernel is placed in queue and will start after kernel1 finishes, CPU continues to next statement
cudaMemcpy(...); // CPU blocks until memory is copied, memory copy starts only after kernel2 finishes
Run Code Online (Sandbox Code Playgroud)

所以在你的例子中,没有必要cudaDeviceSynchronize.但是,调试可能有助于检测哪个内核导致错误(如果有的话).

cudaDeviceSynchronize可能会导致一些放缓,但7-12倍似乎太多了.可能存在时间测量方面的问题,或者内核可能非常快,并且显式同步的开销相对于实际计算时间而言是巨大的.

  • @opetrenko这不是CUDA的工作方式. (3认同)
  • @user3667089 和其他任何人。最有可能的情况是 opetrenko 和 user3667089 的问题是由于代码错误造成的,而不是 NVCC 和 CUDA API 中的错误。由于缺乏可复制的工作示例代码,这场辩论沦为意见。 (3认同)
  • @opetrenko NVCC 不是主机代码的编译器。它是一个交给系统编译器 (gcc) 的预处理器。您对 CUDA 的许多方面都存在误解。您应该发布有关您不知道的事情或遇到的问题的问题,而不是在 SO 上发布误导性信息并伤害他人。也许有人可以澄清为什么你的代码似乎通过添加多余的“cudaDeviceSynchronize”调用而被修复。 (2认同)
  • @opetrenko 请接受我的态度,因为我试图礼貌地要求您不要公开提出不可能的声明(这可能会严重迷惑访问此页面的新手),例如“CUDA 忽略其规范并无序启动内核”,而无需这样做。充分调查了更可能的情况,即错误出现在您自己的代码中,并且遇到了顽固。 (2认同)

lim*_*mes 15

使用cudaDeviceSynchronize()适当的一种情况是当你有几个cudaStream运行时,你想让它们交换一些信息.实际情况就是量子蒙特卡罗模拟中的平行回火.在这种情况下,我们希望确保每个流已经完成运行一些指令并在开始向对方传递消息之前得到一些结果,或者我们最终会传递垃圾信息.使用此命令的原因使程序运行速度变慢,cudaDeviceSynchronize()迫使程序在继续之前等待设备上所有流中所有先前发出的命令完成(来自CUDA C编程指南).正如您所说,内核执行通常是异步的,因此当GPU设备执行您的内核时,CPU可以继续处理其他一些命令,向设备发出更多指令等,而不是等待.但是,当您使用此同步命令时,CPU将被强制为空闲,直到完成所有GPU工作,然后再执行任何其他操作.调试时此行为很有用,因为由于设备代码的异步执行(无论是在一个流还是多个流中),您可能会在看似"随机"的时间内发生段错误.cudaDeviceSynchronize()将强制程序确保流的内核/ memcpys在继续之前完成,这样可以更容易地找出非法访问的发生位置(因为失败将在同步期间显示).


Orp*_*edo 5

当您希望GPU开始处理某些数据时,通常会执行内核调用。当您这样做时,您的设备(GPU)将开始执行您要求执行的任何操作。但是,与主机(CPU)上的常规顺序程序不同,它将继续执行程序中的下一行代码。cudaDeviceSynchronize使主机(CPU)等待,直到设备(GPU)执行完您已启动的所有线程为止,因此您的程序将像正常的顺序程序一样继续执行。

在小型简单程序中,当您使用GPU进行计算时,通常会使用cudaDeviceSynchronize,以避免CPU请求结果和GPU精简计算之间的时间不匹配。使用cudaDeviceSynchronize可以使程序的编写更加容易,但是有一个主要缺点:CPU一直闲置,而GPU进行计算。因此,在高性能计算中,您通常会努力让CPU在等待GPU完成的同时进行计算。