Kernel执行,GPU和Host之间数据Copy,都是有CUDA Stream管理的;
default stream默认不能与其他stream并行执行;即其他stream都结束后,default stream才能开始执行,他结束后,其他stream才能开始执行;(其他stream用cudaStreamCreateWithPriority可以设为和default stream能并行!)
实现Pipeline并行的条件:
1. Host上开辟的是pinned memory;
2. 使用非阻塞的cudaMemcpyAsync;
3. 使用多个Stream
一块卡上能不能同时并行跑来自多个Stream的多个Kernel,取决于GPU核的占用情况(当前Kernel占满了所有核,则不会调度下一个Kernel同时执行;
cudaStreamAddCallback可以让Stream上的某些任务完成后,调用该CPU端函数,该函数结束后,该Stream再执行后续任务;
在一个回调函数中,一定不能进行任何CUDA API的调用,直接的或者间接的都是不可以的。
cudaStreamCreateWithPriority可以创建带优先级的Stream, 并且指定该Stream是否要与default stream是同步的关系(如果指定为异步关系即cudaStreamNonBlocking,则该Stream和default stream可以并行执行)
高优先级的Stream的Kernel, 居然可以抢占低优先级Stream的;profiler图上会显示低优先级Stream的Kernel执行时间变长,其实期间是被抢占了没有真正执行;
用cudaEvent_t来卡时间的好处:1. 可以不用去让host和device同步;2. 更精确;3.可以为多个Stream卡时间;
dynamic parallelism: 在Kernel里再启动子Kernel;可以实现递归调用,但是层数有限制的;
Grid-level Coorperative Group,可以让之前“Kernel结束再起一个Kernel做Reduce”的开销避免,不用新启Kernel就能实现Grid级的同步;
限制就是启动的block数目不能超过硬件和Kernel共同决定的max active block数目(可调API获得这个数目)(这里的active, 指的是SM寄存器和Shared-memory能承受的最大值,不是和core数一样那个)
因为block数目受限,所以性能也许反而下降,因为hide memory访问latency的能力下降了;
Multi-Process Service(MPS):
如果默认多进程使用同一个GPU,即使单个Kernel都占不满GPU,系统也会分时复用该GPU(即时间片轮转调度,独占式);
使用了MPS,多个进程的多个Kernel可以同时在一个GPU上执行(除非一个Kernel占满整个GPU,否则可能会同时把一个Kernel占不满的GPU SM分配给另一个进程的Kernel);
要先启动一个CUDA的daemon进程,然后就不用管了;(本质上是多个进程把Kernel提交给这个daemon进程,由该进程来往GPU上提交任务,所以NVProfiler里看上去,也是同一个进程的多个Stream并行执行的)
多Kernel同时在一个GPU卡上跑的另一个好处是,能Hide其中某些Kernel的访存Latency;
演示了NV Profiler怎么展示多进程的profiling结果;(暂不支持异步MPI调用)
简单的y[i]=a*x[i]+b任务,启动1次Kernel内嵌循环迭代N次,速度10倍于,启动N次Kernel(开销在于启动Kernel时间和读显存至寄存器的时间),速度10倍于,在Kernel里递归启动Kernel调N层(为什么这么慢?)
探讨CUDAStream在GPU计算中的角色,包括Kernel执行、数据Copy管理、Pipeline并行条件及其实现,如使用pinned memory、非阻塞内存复制、多Stream。深入解析Stream与defaultstream的并行性,Kernel抢占机制,以及cudaEvent_t、dynamic parallelism和Grid-level Cooperative Group的使用技巧。同时,介绍Multi-Process Service(MPS)如何改善多进程并行执行效率。
479





