DeepDriving | CUDA编程-05:流和事件

本文来源公众号“DeepDriving”,仅用于学术分享,侵权删,干货满满。

原文链接:CUDA编程-05:流和事件

1 CUDA流

CUDA中有两个级别的并发内核级并发网格级并发。前面的文章DeepDriving | CUDA编程-04:CUDA内存模型-CSDN博客介绍的是内核级并发,这种并发方式是通过数据并行的方式用多个GPU线程去并发地完成一个内核任务,而网格级并发则是把一个任务分解为多个内核任务,通过在一个设备上并发地运行多个内核任务来实现任务的并发执行,这种方式使得设备的利用率更高。CUDA流是一系列异步操作的集合,同一个CUDA流中的操作严格按照顺序在GPU上运行,使用多个流同时启动多个内核任务就可以实现网格级并发。

首先来回顾一下一个典型的CUDA程序的执行流程:

  1. 将数据从host拷贝到device上;

  2. device上执行内核任务;

  3. 将数据从device上拷贝到host上。

这些操作都会在一个CUDA流中运行,如果显式地创建一个流那么这个流就是显式流(非空流)否则就是隐式流(空流),前面文章介绍的CUDA例程都是在隐式流中运行的。如果显式地创建多个流分别去执行上述3个操作步骤,那么不同的CUDA操作是可以重叠进行的,参考下图:

可以看到,使用多个流可以提升整个CUDA程序的运行效率。使用下面的方法可以声明和创建一个显式流:

cudaStream_t stream;
cudaStreamCreate(&stream);

要销毁一个流则可以使用下面的函数

cudaError_t cudaStreamDestroy(cudaStream_t stream);

由于显式流中的操作必须是异步的,而使用cudaMemcpy函数来拷贝数据是一种同步操作,所以必须使用它的异步版本才能在显式流中进行数据拷贝

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

这个函数的最后一个参数用于指定一个流标识符,默认情况下会使用空流。要执行异步的数据传输,那么就必须在host上使用固定内存,因为这样才能确保其在CPU内存中的物理地址在应用程序的整个生命周期内都不会被改变。可以使用下面的两个函数在host上分配固定内存:

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

在非空流中启动内核的时候,必须在内核执行配置中提供一个流标识符作为第4个参数(第3个参数为共享内存的大小,如果没有分配可以设置为0):

kernel_name<<<grid, block, sharedMemSize, stream>>>(...);

显式流的所有操作都是异步的,可以在host代码中调用下面两个函数去检查流中的所有操作是否完成:

cudaError_t cudaStreamSynchronize(cudaStream_t stream);
cudaError_t cudaStreamQuery(cudaStream_t stream);

cudaStreamSynchronize函数会强制阻塞host直到指定流中的所有操作都已经执行完成;cudaStreamQuery函数则不会阻塞host,如果指定流中的所有操作都已完成,它会返回cudaSuccess,否则返回cudaErrorNotReady

2 CUDA事件

一个CUDA事件是CUDA流中的一个标记点,它可以用来检查正在执行的流操作是否已经到达了该点。使用事件可以用来执行以下两个基本任务:

  • 同步流的执行操作

  • 监控device的进展

CUDA提供了在流中的任意点插入并查询事件完成情况的函数,只有当流中先前的所有操作都执行结束后,记录在该流中的事件才会起作用。

声明和创建一个事件的方式如下:

cudaEvent_t event;
cudaError_t cudaEventCreate(cudaEvent_t* event);

调用下面的函数可以销毁一个事件

cudaError_t cudaEventDestroy(cudaEvent_t event);

一个事件可以使用如下函数进入CUDA流的操作队列中

cudaError_t cudaEventRecord(cudaEvent_t event, cudaStream_t stream = 0);

下面的函数会在host中阻塞式地等待一个事件完成

cudaError_t cudaEventSynchronize(cudaEvent_t event);

与流类似的,也可以非阻塞式地去查询事件的完成情况

cudaError_t cudaEventQuery(cudaEvent_t event);

如果想知道两个事件之间的操作所耗费的时间,可以调用

cudaError_t cudaEventElapsedTime(float* ms, cudaEvent_t start, cudaEvent_t stop);

这个函数以毫秒为单位返回开始和停止两个事件之间的运行时间,启动和停止事件不必在同一个CUDA流中。

可以参考以下代码:

cudaEvent_t start, stop;
cudaEventCreate(&start);
cudaEventCreate(&stop);cudaEventRecord(start);
VectorAddGPU<<<block_per_grid, thread_per_block>>>(da, db, dc, size);
cudaEventRecord(stop);cudaEventSynchronize(stop);
float elapsed_time;
cudaEventElapsedTime(&elapsed_time, start, stop);std::cout << "Elapsed time: " << elapsed_time << " ms." << std::endl;cudaEventDestroy(start);
cudaEventDestroy(stop);

3 流同步

CUDA包括两种类型的host-device同步:显示同步和隐式同步。

前面文章中介绍过的很多函数都是隐式同步的,比如cudaMemcpy函数,它会使得host应用程序在数据传输完成之前都会被阻塞。许多与内存相关的操作都带有隐式同步行为,比如:

  • host上的固定内存分配,比如cudaMallocHost

  • device上的内存分配,比如cudaMalloc

  • device上的内存初始化

  • 同一device上两个地址之间的内存拷贝

  • 一级缓存/共享内存配置的修改

CUDA提供了几种显示同步的方法:

  • 使用cudaDeviceSynchronize函数同步device

  • 使用cudaStreamSynchronize函数同步流

  • 使用cudaEventSynchronize函数同步流中的事件

除此之外,CUDA还提供了下面的函数使用事件进行跨流同步:

cudaError_t cudaStreamWaitEvent(cudaStream_t stream, cudaEvent_t event);

该函数可以使指定的流等待指定的事件,该事件可能与同一个流相关,也可能与不同的流相关,如果是不同的流那么这个函数就是执行跨流同步功能。

4 参考资料

  • CUDA C 编程权威指南

  • Professional CUDA C Programming

  • CUDA C Programming Guide

  • CUDA Programming:A Developer's Guide to Parallel Computing with GPUs

THE END !

文章结束,感谢阅读。您的点赞,收藏,评论是我继续更新的动力。大家有推荐的公众号可以评论区留言,共同学习,一起进步。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/853378.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ESP32 BLE学习(0) — 基础架构

前言 &#xff08;1&#xff09;学习本文之前&#xff0c;需要先了解一下蓝牙的基本概念&#xff1a;BLE学习笔记&#xff08;0.0&#xff09; —— 基础概念&#xff08;0&#xff09; &#xff08;2&#xff09; 学习一款芯片的蓝牙肯定需要先简单了解一下该芯片的体系结构&a…

园区地图导航系统:技术原理、部署方案与智能化应用解析

随着智能化时代的到来&#xff0c;园区管理面临诸多挑战。维小帮园区地图导航系统&#xff0c;采用前沿技术&#xff0c;为园区提供全面的导航解决方案&#xff0c;极大提升了园区管理效率和用户体验。 一、园区地图导航系统的功能特点 维小帮园区地图导航系统&#xff0c;以其…

MongoDB 多层级查询

多层级查询 注意&#xff1a;要注意代码顺序 查询层级数据代码放前面&#xff0c;查询条件放后面 if (StringUtils.isBlank(params.getDocType())) {params.setDocType(DOC_TDCTYPE);}String docName mapper.findByDocInfo(params.getDocType());List<ExpertApprovalOpin…

智能化状态管理:自动状态流转处理模块

目录 基本背景介绍 具体实现 基本数据准备 基本数据表 状态转换常量 状态转换注解 任务处理模版 各任务实现逻辑 开启比对任务进行处理 降噪字段处理任务处理 开启业务数据比对处理 业务数据比对处理 开始核对数据生成最终报告处理 核对数据生成最终报告处理 状…

AI项目二十二:行人属性识别

若该文为原创文章&#xff0c;转载请注明原文出处。 分享一个行人属性分析系统&#xff0c;识别行人&#xff0c;并标记每个人的属性。 项目代码来自公众号渡码的项目。 本人用Win10复现完整项目&#xff0c;并记录过程。 源码会上传到github,可以自行下载测试。 Yinyifen…

Flutter 简化CustomPainter的绘制

文章目录 前言一、为何简化&#xff1f;1、通常做法&#xff08;1&#xff09;、绘制形状1&#xff08;2&#xff09;、绘制形状2&#xff08;3&#xff09;、界面显示 2、简化 二、完整代码三、使用示例1、绘制图形2、动态触发绘制 总结 前言 使用Flutter做界面时&#xff0c…

Linux DMA-Buf驱动框架

一、DMABUF 框架 dmabuf 是一个驱动间共享buf 的机制&#xff0c;他的简单使用场景如下&#xff1a; 用户从DRM&#xff08;显示驱动&#xff09;申请一个dmabuf&#xff0c;把dmabuf 设置给GPU驱动&#xff0c;并启动GPU将数据输出到dmabuf&#xff0c;GPU输出完成后&#xf…

大数据实训项目(小麦种子)-02、实训项目整体功能介绍与演示

文章目录 前言界面及功能描述实现功能描述技术选型界面展示首页界面功能1&#xff1a;HDFS&#xff0c;选择文件上传文件详细步骤 功能2&#xff1a;MapReduce预处理数据功能3&#xff1a;Hbase存储小麦种子数据并查询前10条记录功能4&#xff1a;Hive分析原始csv文件数据并ech…

RTA_OS基础功能讲解 2.9-警报器

RTA_OS基础功能讲解 2.9-警报器 文章目录 RTA_OS基础功能讲解 2.9-警报器一、警报器简介二、警报器配置2.1 激活一个任务2.2 设置一个事件2.3 执行回调函数2.4 递增一个(软件)计数器三、警报器设置3.1 绝对警报3.1.1 单次触发3.1.2 周期触发3.1.3 在过去设置警报3.1.4 将绝对…

swift微调牧歌数据电商多模态大语言模型

大规模中文多模态评测基准MUGE_数据集-阿里云天池多模态理解和生成评估挑战榜(MUGE)是由阿里巴巴达摩院智能计算实验室发起,由阿里云天池平台承办,并由浙江大学、清华大学等单位共同协办。 Mhttps://tianchi.aliyun.com/dataset/107332微调的是牧歌数据集,结果都不好,记录…

中望CAD 2025 (ZW3D2025) 简体中文修改版

名称&#xff1a;中望CAD 2025 (ZW3D2025) 简体中文修改版 描述&#xff1a;一款三维CAD设计工具&#xff0c;运行破解补丁ZW3D2025-2024-Patch执行修补。 链接&#xff1a;夸克网盘分享 &#x1f4c1; 大小&#xff1a;3.2GB &#x1f3f7; 标签&#xff1a;#PC软件 #CAD #设…

支付宝 沙盒demo使用

简介&#xff1a;支付宝沙箱环境是一个为开发者提供的模拟测试环境&#xff0c;用于在应用上线前进行接口功能开发和联调。在这个环境中&#xff0c;开发者可以模拟开放接口&#xff0c;进行开发调试工作&#xff0c;以确保应用上线后能顺利运行。 1. 配置沙盒 1. 1 沙箱控制…

【odoo15】前端自定义模态弹窗

概要 在odoo15或者在15之前&#xff0c;odoo前端的owl框架还没完全替换当前前端框架的时候&#xff0c;我们很多时候都是用js或者jq来直接操作dom&#xff0c;那么我们如果需要在前端用到一个模态弹窗&#xff0c;可以怎么解决呢&#xff1f; 方法1 直接用js原生的模态弹窗&am…

Oracle的这些BUG你要遇到,说明你是一个DBA老鸟...

作者&#xff1a;IT邦德 中国DBA联盟(ACDU)成员&#xff0c;10余年DBA工作经验&#xff0c; Oracle、PostgreSQL ACE CSDN博客专家及B站知名UP主&#xff0c;全网粉丝10万 擅长主流Oracle、MySQL、PG、高斯及Greenplum备份恢复&#xff0c; 安装迁移&#xff0c;性能优化、故障…

【LVGL】Guider 界面分析

文章目录 前言架构创建 UI切换界面空间释放分析创建页面空间变化 前言 分析Gui Guider-1.7.2-GA 生成的 LVGL 界面切换&#xff0c;资源管理等处理 架构 所有控件存放于同一个结构体 lv_ui 内&#xff0c;每个页面都至少包含 screen_xxx 和 screen_xxx_del 两个成员 typede…

用HAL库改写江科大的stm32入门-7-1 ADC

实验目的:了解ADC基本概念 电路图&#xff1a; ADC&#xff08;Analog-Digital Converter&#xff09;模拟-数字转换器&#xff0c;它可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量&#xff0c;建立模拟电路到数字电路的桥梁。 实验效果&#xff1a; &#xff0…

【html】学会这一套布局,让你的网页更加

很多小伙伴们在刚刚开始学习网页设计的时候不知道怎么布局今天给大家介绍一种非常实用且更加专业的一种布局。 灵感来源&#xff1a; 小米官网 布局图; 实例效果图&#xff1a; 这是一个简单的HTML模板&#xff0c;包括头部、内容区域和底部。 头部部分包括一个分为左右两部分…

【代码随想录】【算法训练营】【第39天】 [62]不同路径 [63]不同路径II [343]整数拆分 [96]不同的二叉搜索树

前言 思路及算法思维&#xff0c;指路 代码随想录。 题目来自 LeetCode。 day 39&#xff0c;周六&#xff0c;坚持不住了~ 题目详情 [62] 不同路径 题目描述 62 不同路径 解题思路 前提&#xff1a;每次只能向下或者向右移动一步 思路&#xff1a;动态规划&#xff0…

部署LVS-DR群集...

目录 最后一台主机&#xff08;第四台&#xff09; 本地yum源安装httpd&#xff08;非必做&#xff09; 继续开始从最后一台主机开始&#xff08;第四台&#xff09; 转第二台主机 转第三台主机 回第二台 上传 转第三台主机 上传 回第二台 转第三台 转第一台主机…

Java 项目学习(初始化项目)

后端工程基于 maven 进行项目构建&#xff0c;并且进行分模块开发 参考&#xff1a;Spring或Spring Boot项目目录结构划分和代码分层 1、了解项目的整体结构 sky-take-out maven 父工程&#xff0c;统一管理依赖版本&#xff0c;聚合其他子模块 sky-common 子模块&#xff0c…