CUDA与TensorRT(3)之CUDA stream&Event&NVVP

1.CUDA Stream

(1)分类
  • 是隐式流(默认流,NULL流);所有的CUDA操作都默认运行在默认流里面,并且这里面的GPU task和CPU端都是同步的
  • 显示流显示流里面的GPU task和CPU端计算是异步的,不同显示流内的GPU task也是异步的
(2)相关的API
  • 定义:cudaStream_t stream
  • 创建:cudaStreaCreate(&stream)
  • 数据传输时:cudaMemcpyAsyn(dst, src, size, type, stream)
  • kernel在流中执行调用时:kernel_name<<<grid,block,shareMemSize,stream>>>(argument list)
  • 同步流和查询流是否完成:
    • cudaError_t cudaStreamSynchronize(cudaStream_t stream)
    • cudaError_t cudaStreamQuery(cudaStream_t stream)
  • 流的销毁:cudaError_t cudaStreamDestroy(cudaStream_t stream)
(3)CUDA Stream优点
  • CPU计算和Kernel计算并行
  • CPU计算和数据传输并行
  • 数据传输和Kernel计算并行
  • Kernel计算并行

需要注意的

  • 显示流里的GPU task与CPU端task的执行是异步的,使用stream一定要注意同步;
  • 上面的cudaStreamSynchronize是同步一个流,而cudaDeviceSynchronize是同步该设备(后面有解释)上的所有流;
(4)数据传输和GPU计算重叠的demo

在这里插入图片描述

这其中要求数据量和计算量足够大,不然达不到上图最下面这个效果,也没有流的优势了。

但是上图中为什么H2D和D2H为什么没有重叠呢
因为CPU和GPU之间的数据传输是经过PCIe总线的,PCIe上的操作是顺序的。
带有双工PCIe总线的设备可以重叠两个数据传输,但他们必须在不同呢的流和不同方向上。

(5)CUDA优先级
  • 要求:GPU算力3.5以上,即Kepler架构及以上
  • API:cudaError_t cudaStreamCreateWithPriority(cudaStream_t *pStream, unsigned int flags, int priority)
  • cudaError_t cudaDeviceGetStreamPriorityRange(int *leastPriority)
  • 特点:只对kernel有效,较低的整数值表示较高的流优先级,很少用。
(6)CUDA Stream为什么有效

多流为什么会有效,流越多越好么?

  • PCIe总线传输速度慢,是瓶颈,会导致传输数据的时候GPU处于空闲等待状态。多流可以实现数据传输与kernel计算的并行。
  • 一个kernel往往用不了整个GPU的算力。多流可以让多个kernel同时计算,充分利用GPU算力。
  • 不是流越多越好。GPU内可同时并行执行的流数量是有限的。

计算密集型:耗时在计算,一次访存,数十次甚至上百次计算
访存密集型:耗时在访存,一次访存,几次计算
GPU一般处理简单可并行计算,大部分kernel都是访存密集型
CUDA加速,kernel合并,将小任务合并成大任务(但不是大任务变成更大哈),更有效
在这里插入图片描述

(6)默认流的表现

单线程内,默认流的执行是同步的(本部分讨论的默认流是设置了多个流的情况)
但是在编译的时候加上–defual-stream per-thread 后,默认流的执行也是异步的了。
当然在这两种情况中,显示流一直是异步的。

多线程情况下,编译的时候不加上述参数的话,就是多线程共享一个默认流。
加了上述参数进行编译的话,就是每个线程有一个默认流。


2.CUDA Event

在stream中插入一个事件,类似于打一个标记位,用来记录stream是否执行到当前位置。Event有两个状态,已被执行和未被执行。

  • 定义:cudaEvent_t event
  • 创建:cudaError_t cudaEventCreate(cudaEvent_t* event);
  • 插入流中:cudaError_t cudaEventRecord(cudaEvent_t event, cudaStream_t stream = 0);
  • 销毁:cudaError_t cudaEventDestroy(cudaEvent_t event);
  • 同步和查询
    • cudaError_t cudaEventSynchronize(cudaEvent_t event);
    • cudaError_t cudaEventQuery(cudaEvent_t event);
  • 进阶同步函数cudaError_t cudaStreamWaitEvent(cudaStream_t stream, cudaEvent_t event);
(1)最常使用–测时间

在这里插入图片描述


3.CUDA 同步操作

CUDA中的显式同步按粒度可以分为四类

(1)device synchronize 影响很大

在这里插入图片描述

(2)stream synchronize 影响单个流和CPU

在这里插入图片描述

(3)event synchronize 影响CPU,更细粒度的同步

在这里插入图片描述

(4)cudaError_t cudaStreamWaitEvent(cudaStream_t stream, cudaEvent_t event);

(太复杂,基本不用)在这里插入图片描述

4.NVVP操作

NVIDIA Visual Profiler(NVVP)是NVIDIA推出的跨平台的CUDA程序性能分析工具。

• 随CUDA安装,不需要额外安装。

• 可自定义配置+图形化界面,可以快速找到程序中的性能瓶颈。

• 以时间线的形式展示CPU和GPU操作。

• 可以查看数据传输和kernel的各种软件参数(速度,kernel启动时间等)和硬件参数(L1 cache命中率等)。

(1)Windows中使用

打开nvvp

• File->New Session

• 在File里选择CUDA程序bin

• 选择执行

(2)Linux中使用
  • 方法一:使用命令nvprof ./cuda_bin
  • 方法二:nvprof -o cuda_bin.nvvp ./cuda_bin,将cuda_bin.nvvp传回windows,使用NVVP打开(要求cuda版本一致)
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值