6.4_CUDA事件:计时

6.4 CUDA事件:计时

当之前的命令已经完成时,CUDA事件开始运行,提交给GPU一个命令。该命令使GPU写一个已知的值到一个32位的内存位置。CUDA驱动程序通过检测该32位的值来实现cuEventQuery()和cuEventSynchronize()。但是除了32位的“跟踪值”,GPU也可以写一个源于高分辨率GPU时钟的64位时间值。

因为它们使用了GPU时钟,使用CUDA事件的计时较少受到系统事件(如页面错误或中断)的干扰,并且根据时间戳计算运行时间的函数适用于所有操作系统。所谓操作的系统时间(wall time)是指用户最终感受到的时间的流逝,所以CUDA事件最好有针对性地使用在内核性能调优或其他GPU密集型的操作上,而不是报告绝对时间给用户。

cuEventRecord()的流参数是针对流间同步的,而不是针对计时的。当使用CUDA事件来计时时,最好把它们记录在NULL流中。其机理和在超标量CPU读取时间戳计数器(如基于x86的RDTSC)的清空流水线的指令的理由一样:在所有的GPU引擎上强制执行“汇集”操作,可以避免正在被计时的操作产生任何歧义[1]。确保

cu(da)EventRecord()调用包含足够的工作以便计时获得有意义的结果。

最后,请注意,CUDA事件旨在对GPU操作计时。任何同步的CUDA操作都将导致使用GPU来对CPU/GPU同步操作进行计时。

CUDART_CHECK(udaEventRecord( startEvent, NULL)); // synchronous memcpy - invalidates CUDA event timing  
CUDART_CHECK(udaMemcpy( deviceIn, hostIn, N*sizeof(int));  
CUDART_CHECK(udaEventRecord( stopEvent, NULL));

在下一节探讨的例子中,我们将展示如何使用CUDA事件来计时。

[1] 其他考虑:在CUDA的SM 1.1硬件上,计时事件可能只由执行内核计算的硬件单元来记录。