在为 CUDA 内核计时时,以下内容不起作用,因为内核在执行时不会阻止 CPU 程序执行:
start timer
kernel<<<g,b>>>();
end timer
我已经看到了三种(成功)定时 CUDA 内核的基本方法:
(1) 两个 CUDA eventRecords。
float responseTime; //result will be in milliseconds
cudaEvent_t start; cudaEventCreate(&start); cudaEventRecord(start); cudaEventSynchronize(start);
cudaEvent_t stop; cudaEventCreate(&stop);
kernel<<<g,b>>>();
cudaEventRecord(stop); cudaEventSynchronize(stop);
cudaEventElapsedTime(&responseTime, start, stop); //responseTime = elapsed time
(2) 一个 CUDA 事件记录。
float start = read_timer(); //helper function on CPU, in milliseconds
cudaEvent_t stop; cudaEventCreate(&stop);
kernel<<<g,b>>>();
cudaEventRecord(stop); cudaEventSynchronize(stop);
float responseTime = read_timer() - start;
(3) deviceSynchronize 代替 eventRecord。(可能仅在在单个流中使用编程时有用。)
float start = read_timer(); //helper function on CPU, in milliseconds
kernel<<<g,b>>>();
cudaDeviceSynchronize();
float responseTime = read_timer() - start;
我通过实验验证了这三种策略产生相同的时序结果。
问题:
- 这些策略的权衡是什么?这里有什么隐藏的细节吗?
- 除了在多个流中计时多个内核之外,使用两个事件记录和
cudaEventElapsedTime()
函数有什么好处吗?
您可能可以使用您的想象力来弄清楚是什么read_timer()
。尽管如此,提供一个示例实现也无妨:
double read_timer(){
struct timeval start;
gettimeofday( &start, NULL ); //you need to include <sys/time.h>
return (double)((start.tv_sec) + 1.0e-6 * (start.tv_usec))*1000; //milliseconds
}