是否有必要在对CUDA内核的两次调用之间使用同步?
到目前为止,我已经编写了在程序中只调用一次内核的程序
所以我有一个内核
__global__ void someKernel(float * d_in ){ //Any parameters
//some operation
}
我基本上是这样做的
main()
{
//create an array in device memory
cudaMalloc(......);
//move host data to that array
cudaMemcpy(......,cudaMemcpyHostToDevice);
//call the kernel
someKernel<< <nblocks,512>> >(.......);
//copy results to host memory
cudaMemcpy(......,cudaMemcpyDeviceToHost);
// Point to notice HERE
}
它工作正常。但是这次我想不仅一次而且多次调用内核 类似
main()
{
//create an array in device memory
cudaMalloc(......);
//move host data to that array
cudaMemcpy(......,cudaMemcpyHostToDevice);
//call the kernel
someKernel<< <nblocks,512>> >(.......);
//copy results to host memory
cudaMemcpy(......,cudaMemcpyDeviceToHost);
// From here
//Some unrelated calculations here
dothis();
dothat();
//Then again the kernel repeteadly
for(k: some_ks)
{
// Do some pre-calculations
//call the kernel
someKernel<< <nblocks,512>> >(.......);
// some post calculations
}
}
我的问题是我应该在第一次调用内核和在 for 循环中(以及在每次迭代中)调用内核之间使用某种同步cudaDeviceSynchronize吗?或者没有必要?
回答
在这种情况下,至少有两个原因不需要额外的同步。
-
cudaMemcpy已经是一个同步调用。它会阻塞 CPU 线程并等待所有先前发送给该设备的 CUDA 活动完成,然后才允许开始数据传输。一旦数据传输完成,就允许 CPU 线程继续进行。 -
除非使用 CUDA流,否则发给单个设备的 CUDA 活动不会以任何方式重叠。您没有使用流。因此,即使是向设备发出的异步工作也将按发出顺序执行。按该顺序发给设备的项目 A 和 B 不会相互重叠。项目 A 将在项目 B 开始之前完成。这是一个主要的 CUDA 流语义点。