我正在研究一个简单的cuda程序,其中我发现90%的时间来自单个语句,这是从设备到主机的cudamemcpy。该程序在600-700微秒内将数据从主机传输到设备大约2MB,并在10ms内将4MB数据从设备复制回主机。我的计划所用的总时间是13毫秒。我的问题是,为什么从设备到主机和主机到设备的两次复制存在不对称性。是因为cuda devlopers认为复制通常会以字节为单位。我的第二个问题是有没有办法绕过它。
我使用的是带有343核和1GB内存的Fermi GTX560显卡。
答案 0 :(得分:2)
CUDA功能的时序与CPU略有不同。首先,请确保您不要在应用程序启动时调用CUDA函数来考虑CUDA的初始化成本,否则可能会在您开始计时时初始化。
int main (int argc, char **argv) {
cudaFree(0);
....//cuda is initialized..
}
使用像这样的Cutil计时器
unsigned int timer;
cutCreateTimer(&timer);
cutStartTimer(timer);
//your code, to assess elapsed time..
cutStopTimer(timer);
printf("Elapsed: %.3f\n", cutGetTimerValue(timer));
cutDeleteTimer(timer);
现在,经过这些初步步骤后,我们来看看问题。调用内核时,CPU部件将暂停,直到调用传递给GPU。 GPU继续执行,同时CPU继续执行。如果你调用cudaThreadSynchronize(..),那么CPU将停止,直到GPU完成当前调用。 cudaMemCopy操作还需要GPU来完成其执行,因为请求内核应该填充的值。
kernel<<<numBlocks, threadPerBlock>>>(...);
cudaError_t err = cudaThreadSynchronize();
if (cudaSuccess != err) {
fprintf(stderr, "cudaCheckError() failed at %s:%i : %s.\n", __FILE__, __LINE__, cudaGetErrorString( err ) );
exit(1);
}
//now the kernel is complete..
cutStopTimer(timer);
因此在调用停止计时器功能之前进行同步。如果在内核调用后放置内存副本,则内存复制的已用时间将包括内核执行的某些部分。因此,可以在定时操作之后放置memCopy操作。
还有一些探查器计数器可用于评估内核的某些部分。
How to profile the number of global memory transactions for cuda kernels?