转自 GPU and Computing 公众号
在先前的文章中《近距离看GPU计算(2)》我们介绍了GPU SM单元以Thread Block为单位的调度方法,这些的Block属于同一个kernel任务,当然处于相同的进程上下文(CUDA Context),针对的是任务内线程级别并行执行。我们知道现代GPU计算能力与日俱增,不断挑战新高。随之而来的问题是,单凭一个Kernel任务很能占满GPU,来自相同进程,甚至不同的进程的任务在时间上、空间上如何共享GPU,又是如何调度的呢?笔者曾经就这些问题求教于GPU公司专门的同事,给出的解释往往含混不清,很难有确定的答案。这里笔者不是自不量力要祭出终极大杀器,而是就一些文献浅见,尝试梳理下思路提出问题,望有识见的朋友能给与指正。主题内容大概分三个部分,第一部分我们讨论来自同一进程的任务的调度,第二部分会涉及来自不同进程上下文的任务如何共享GPU以及可能抢占的行为,第三部分会谈下GPU驱动框架对调度行为的一些支持。第一二部分主要讨论硬件的行为,第三部分从软件的视角分析。本文为其中第一部分。
在正式开始介绍之前,我们先回顾下CUDA框架跟任务调度关系密切的stream的概念。Stream表示一个GPU任务队列,该队列中的任务将按照添加到Stream中的顺序先后而依次执行。所有的CUDA任务(包括kernel运行和数据搬运)都显式或隐式通过stream得到执行,stream也就两种类型,分别是:默认stream(defaut stream, 或者说stream 0)和其它stream。CUDA任务没有显式的指定stream就运行在默认str