如何理解CUDA Stream?

如何理解CUDA Stream?

参考

CUDA随笔之Stream的使用 - 知乎 (zhihu.com)

CUDA ---- Stream and Event - 苹果妖 - 博客园 (cnblogs.com)

背景

CUDA程序并发性可分为两种:

1、kernel level concurrency:一个task由GPU上多个thread并行执行的。(我们前几张介绍的都是kernel level的开发)

2、grid level level concurrency:多个task在GPU上同时执行。

(一切为了速度,冲冲冲!)

多个task并行执行会遇到一个问题,假设后续某个任务需要前面某个任务的结果,如果它们都同一时间执行,程序会崩溃的。那么,自然而然我们引出一个概念:stream。

==CUDA stream是将主机上的多个kernel进行某种顺序的排序。==

通过stream可以控制多个kernel在设备上的顺序。不同的stream互不影响。通常情况下,执行kernel比GPU-CPU传输数据的时间要长。因此,某些情况下可以将kernel的执行操作和数据传输放到不同的stream中,用kernel的时间掩盖传输时间,缩短程序运行时间。

通常情况下,执行kernel比GPU-CPU传输数据的时间要长。因此,某些情况下可以将kernel的执行操作和数据传输放到不同的stream中,用kernel的时间掩盖传输时间,缩短程序运行时间。

可以把传输数据的时间,湮灭掉。

CUDA stream可分为两种操作:

1、同步:此状态会阻塞CPU进程,直到kernel操作完成。

2、异步:此状态在唤醒kernel函数后立刻将控制权交给CPU。

还记得我们上一节介绍的SM等硬件的知识吗?这里也一样,从软件层面上看,不同的stream是同时进行的,但在硬件层面上还需要去争夺SM资源,可能需要相互等待。

GPU编程与优化实践 - 知乎 (zhihu.com)

CUDA stream可以显式或隐式调用。在前几张实例中,虽然我们在代码中没有任何stream的操作,但实际上系统会自动分配一个隐式stream,所有的kernel都在这一个stream上,如以下操作,cudaMemcpy会阻塞cpu进程,直到数据传输操作完成。

但假如我们相对多个kernel的执行顺序进行操作,则必须申请一个或多个显式stream进行管理。例如在以下情形中:

1、重叠host和device的计算。

2、重叠host计算与cpu-gpu的数据传输。

3、重叠device计算与cpu-gpu的数据传输。

4、gpu的并发计算

cudaMemcpyAsync可以执行异步操作,在数据传输过程中,将操作权交给cpu进行控制。

cudaError_t cudaMemcpyAsync(void* dst, const void* src, size_t count,
    cudaMemcpyKind kind, cudaStream_t stream = 0);

申请cuda stream:

cudaError_t cudaStreamCreate(cudaStream_t* pStream);

在异步传输数据时必须使用固定/不可分页的主机内存,可使用以下APT申请:

cudaError_t cudaMallocHost(void **ptr, size_t size);
cudaError_t cudaHostAlloc(void **pHost, size_t size, unsigned int flags);

image-20230925163452000

CUDA Events是cuda stream中的标记。(类似跑马拉松,把整个路程分为一段段的,每一段的路标就是一个events)Event只是一个标志,你可以用来查询stream的状态:

1、同步stream的执行

2、监控device进度

CUDA允许在任何一个点插入event,并查询该event是否完成。只有当该事件段中所有操作都被满足,event才会标志为完成。

events的声明,创建,销毁:

cudaEvent_t event;

cudaError_t cudaEventCreate(cudaEvent_t* event);

cudaError_t cudaEventDestroy(cudaEvent_t event);

CUDA ---- Stream and Event - 苹果妖 - 博客园 (cnblogs.com)

这个博客写的也非常系统:


请在这里,系统地学习CUDA编程

CUDA Zone - Library of Resources | NVIDIA Developer

CUDA Toolkit Documentation 12.2 (nvidia.com)


CUDA优化方案—stream的使用_cudastream_t_A晨的博客的博客-CSDN博客

image-20230925165243515

CUDA Stream的高阶用法:

//创建多个流
cudaStream_t stream[3];
for(int i=0; i<3; i++)
    cudaStreamCreat(&stream[i]);

float* hostPtr;
cudaMallocHost(&hostPtr, 3*size);
......
//开启了三个流,将数据分成三份分别交给了三个流进行计算
for(int i=0; i<3; i++){
    //从CPU内存复制数据到GPU显存
    cudaMemcpyAsync(DevPtr + i*size, hostPtr + i*size, size, cudaMemcpyHostToDevice, stream[i]);
    //执行Kernel函数
    Mykernel<<<grid, block, 0, stream[i]>>>(outputDevPtr + i*size, size, cudaMemcpyDeviceToHost, stream[i]);
    //将结果拷贝回CPU内存
    cudaMemcpyAsync(hostPtr + i*size, outputDevPtr + i*size, size, cudaMemcpyDeviceToHost, stream[i]);
}
//同步流
for(int i=0; i<3; i++)
    cudaStreamSynchronise(stream[i]);
//销毁流
for(int i=0; k<3; i++)
    cudaStreamDestroy(stream[i]);

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值