什么时候cudaDeviceSynchronize
真的需要调用这个函数?
据我从CUDA文档中了解,CUDA内核是异步的,因此我们应该cudaDeviceSynchronize
在每次内核启动后调用它们.但是,cudaDeviceSynchronize
在时间测量之前,除了一个之外,我尝试了相同的代码(训练神经网络).我发现我得到了相同的结果,但速度在7-12x之间(取决于矩阵大小).
所以,问题是是否有任何理由使用cudaDeviceSynchronize
时间测量.
例如:
是否需要先将数据从GPU复制回主机cudaMemcpy
?
如果我做矩阵乘法,比如
C = A * B
D = C * F
Run Code Online (Sandbox Code Playgroud)我应该放在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倍似乎太多了.可能存在时间测量方面的问题,或者内核可能非常快,并且显式同步的开销相对于实际计算时间而言是巨大的.
lim*_*mes 15
使用cudaDeviceSynchronize()
适当的一种情况是当你有几个cudaStream
运行时,你想让它们交换一些信息.实际情况就是量子蒙特卡罗模拟中的平行回火.在这种情况下,我们希望确保每个流已经完成运行一些指令并在开始向对方传递消息之前得到一些结果,或者我们最终会传递垃圾信息.使用此命令的原因使程序运行速度变慢,cudaDeviceSynchronize()
迫使程序在继续之前等待设备上所有流中所有先前发出的命令完成(来自CUDA C编程指南).正如您所说,内核执行通常是异步的,因此当GPU设备执行您的内核时,CPU可以继续处理其他一些命令,向设备发出更多指令等,而不是等待.但是,当您使用此同步命令时,CPU将被强制为空闲,直到完成所有GPU工作,然后再执行任何其他操作.调试时此行为很有用,因为由于设备代码的异步执行(无论是在一个流还是多个流中),您可能会在看似"随机"的时间内发生段错误.cudaDeviceSynchronize()
将强制程序确保流的内核/ memcpys在继续之前完成,这样可以更容易地找出非法访问的发生位置(因为失败将在同步期间显示).
当您希望GPU开始处理某些数据时,通常会执行内核调用。当您这样做时,您的设备(GPU)将开始执行您要求执行的任何操作。但是,与主机(CPU)上的常规顺序程序不同,它将继续执行程序中的下一行代码。cudaDeviceSynchronize使主机(CPU)等待,直到设备(GPU)执行完您已启动的所有线程为止,因此您的程序将像正常的顺序程序一样继续执行。
在小型简单程序中,当您使用GPU进行计算时,通常会使用cudaDeviceSynchronize,以避免CPU请求结果和GPU精简计算之间的时间不匹配。使用cudaDeviceSynchronize可以使程序的编写更加容易,但是有一个主要缺点:CPU一直闲置,而GPU进行计算。因此,在高性能计算中,您通常会努力让CPU在等待GPU完成的同时进行计算。
归档时间: |
|
查看次数: |
58507 次 |
最近记录: |