找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 258|回复: 1

DAY11:阅读CUDA异步并发执行中的Event和同步调用

[复制链接]
发表于 2018-5-13 23:00:24 | 显示全部楼层 |阅读模式
QQ图片20180503112158.jpg

前情回顾:
DAY5:阅读 CUDA C编程接口之CUDA C runtime
今天内容比较简单,讲解Events和同步调用。自此,关于异步并发执行部分的1.主机与GPU之间的并发执行;2.内核并发执行;3.数据传输和内核执行之间的重叠;4.并行数据传输;5.Stream;6.Event;7.同步调用 就全部讲完。

3.2.5.6. Events
The runtime also provides a way to closely monitor the device's progress, as well as perform accurate timing, by letting the application asynchronously record events at any point in the program and query when these events are completed. An event has completed when all tasks - or optionally, all commands in a given stream - preceding the event have completed. Events in stream zero are completed after all preceding tasks and commands in all streams are completed.
3.2.5.6.1. Creation and Destruction
The following code sample creates two events:
QQ图片20180514142625.png
They are destroyed this way:
QQ图片20180514142637.png
3.2.5.6.2. Elapsed Time
The events created in Creation and Destruction can be used to time the code sample of Creation and Destruction the following way:
3.2.5.7. Synchronous Calls
When a synchronous function is called, control is not returned to the host thread before the device has completed the requested task. Whether the host thread will then yield, block, or spin can be specified by calling cudaSetDeviceFlags()with some specific flags (see reference manual for details) before any other CUDA call is performed by the host thread.
QQ图片20180514142650.png

回复

使用道具 举报

 楼主| 发表于 2018-5-14 14:18:10 | 显示全部楼层
本文备注/经验分享

Events就是事件,而事件是用来同步和时间测量的一种机制,请注意英文教材中的同步往往和中文教材的同步意思不同,英文(例如国外教材)中的同步往往叫查询操作也叫同步。所以精确的说,事件是用来同步,查询完成状态,以及测量时间的一种机制。CUDA允许使用不带用测时功能的事件。如果选择了不带测时功能,则只有前面两种功能了(阻塞式的等待同步,和轮询式的非阻塞同步,或者用户也可以选择这两种的综合---例如先轮询一段时间,然后再阻塞等待,请注意用户选择的阻塞式等待是从用户的角度来看的。Runtime/Driver可以继续将用户的逻辑角度的阻塞等待继续实现成轮询,或者直接阻塞,或者轮询一段时间后再阻塞。)。

They are destroyed this way:event没有停止的概念,只有发生了(实际的被recorded了)和没有发生。你看到的函数是销毁这两个event,往往在程序结束的时候出现(类似的,也有cudaFree()等伴随出现。后者是释放显存)。只有event发生了,和没有发生。没有开始和停止的说法的,发生了可以带着一个时刻,请注意是时刻(例如3点5分),而不是时间长短,正因为是时刻,你需要2个events,将他们发生的时刻相减,才能得到时间。所以你看到的测时代码都用来2个events,而不是1个。record event 1, 启动kernel, record event 2,你知道流是顺序执行的。那么当event 2发生后,kernel已经执行完了,event 1也发生了,而此时,你得到了2个时刻(event 2和event 1的发生时刻),两个相减,就是中间的kernel的执行时间。你可能会怀疑,event本身被record的过程,不需要时间么?这个非常非常快,可以忽略。

Elapsed Time流逝的时间,就是刚才说过的,流中:event 1,kernel(或者多个kernel等),event 2,然后只要等待event 2完成了,然后用event 2的时刻,再和event 1的时刻做减,就能得到中间的kernel(或者多个kernel等操作)的用时了。

Synchronous Calls这就是常规的调用(同步调用,阻塞调用),很多无Async结尾的CUDA函数,都是同步调用的。(在CUDA函数完成前不返回控制权给host thread,host thread将被block住。)

Whether the host thread will then yield, block, or spin can be specified by calling cudaSetDeviceFlags()with some specific flags (see reference manual for details) before any other CUDA call is performed by the host thread. 当从host程序的逻辑角度看,某阻塞式函数(例如cudaMalloc, 例如cudaMemcpy)将导致host线程暂停运行,也就是看上去阻塞在这些普通函数上了,不过内地里,究竟Runtime或者Driver是将在那里真的阻塞,还是在那里反复轮训自旋,还是yield放弃时间片,是内部实现的问题。你可以强制通过cudaSetDeviceFlags()来要求一种。小提示:如果不是启动非常非常小的kernel,建议总是选择阻塞。非常非常小的kernel,非常短时间就能返回的,建议选择spin,或者yield。我的习惯是上去就选择BlockingSync要求阻塞。因为我从来不写非常非常小的kernel,执行时间在us级别的那种。轮询Spin适合非常小的kernel的,可以有更低的延迟,但为何我们几乎不需要选他?因为(1)几乎没有人写这么短暂就结束的小kernel,(2)往往我们调度都是一次性发布大量的命令给一个Queue中的,而很少有人一个小kernel结束就立刻需要host端判断结果,进行下一步的其他可能命令发布。根据实际来看,BlockingSync总是有更好的性能的,而不是手册的说法。上面的第二个,可以改成设备端的动态并行,这个比你在host上自旋轮询,延迟更低。不过动态并行需要计算能力3.5+的卡。总之建议用户总是设定BlockingSync的设备标志。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

快速回复 返回顶部 返回列表