CUDA流和事件

news2024/11/18 4:46:13

CUDA通过流来实现网格级并发。

流和事件

CUDA流是一系列异步的CUDA操作,这些操作按照主机代码确定的顺序在设备上执行。流可以封装这些操作,保持操作的顺序,允许操作在流中排队,并使他们在先前的所有操作之后执行。

这些操作包括在主机与设备之间进行数据传输,内核启动以及大多数由主机发起但由设备处理的其他命令。

流中操作的执行相对于主机总是异步的。CUDA运行时决定何时可以在设备上执行操作。我们的任务是使用CUDA的API来确保一个异步操作在运行结果被使用之前可以完成。

在同一个CUDA流中的操作有严格的执行顺序,而在不同的CUDA流中的操作在执行顺序上不受限制。使用多个流同时启动多个内核,可以实现网格级并发。

CUDA编程的一个典型模式是:

  1. 数据从主机移到设备上
  2. 设备上执行一个内核
  3. 将结果从设备移回主机

在多数情况下,执行内核比传输数据耗时的多。在这些情况下,可以完全隐藏CPU和GPU之间的通信延迟。将内核执行和数据传输调度到不同的流中,这些操作可以重叠,程序的总运行时间将被缩短。流在CUDA的API调用粒度上可实现流水线或双缓冲技术。

CUDA的api函数分为同步和异步。同步函数会阻塞主机端线程,直到其完成。异步函数被调用后,控制权直接移回主机。异步函数和流是在CUDA中构建网格级并发的两个基本支柱。

CUDA流

所有的CUDA操作(内核和数据传输)都在一个流中显式或隐式的运行。流分为两种:

  • 隐式声明的流(空流)
  • 显式声明的流(非空流)

如果没有显式的声明一个流,那么内核启动和数据传输将默认使用空流。

非空流可以被显式的创建和管理。如果想要重叠不同的CUDA操作,必须使用非空流。基于流的异步的内核启动和数据传输支持以下类型的并发:

  • 重叠主机计算和设备计算
  • 重叠主机计算和主机与设备间的数据传输
  • 重叠主机与设备间的数据传输和设备计算
  • 并发设备计算

思考下面使用默认流的方法:

cudaMemcpy(...,cudaMemcpyHostToDevice);
kernel<<<grid,block>>>();
cudaMemcpy(...,cudaMemcpyDeviceToHost);

从设备角度来看,上述代码的所有3个操作都被发布到默认流中,并且按发布顺序执行。设备不知道其他被执行的主机操作。

从主机角度看,数据传输是同步的,强制空闲主机等待数据传输完成。内核启动是异步的,无论内核是否完成,主机的应用程序都立即恢复执行。这种内核启动的默认异步行为使它可以直接重叠设备和主机计算

数据传输也可以异步发布,但是必须显式的设置一个CUDA流来装载。提供以下函数

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

附加的流的标识符作为第五个参数,默认情况下使用默认流。这个函数与主机是异步的,所以调用发布后,控制权将立即返回到主机。

使用如下代码创建一个非空流

cudaError_t cudaStreamCreate(cudaStream_t* pStream);

该函数创建了一个可以显示管理的非空流。之后,返回到pStream中的流就可以被当做流参数供其他的异步CUDA的API函数使用。

在执行异步数据传输时,必须使用固定主机内存。在非默认流中启动内核,必须在内核执行配置中提供一个流标识符作为第四个参数

kernel<<<grid, block, shareMemSize, stream>>>()

非默认流的声明和创建如下:

cudaStream_t stream;
cudaStreamCreate(&stream);

//释放资源
cudaStreamDestroy(cudaStream_t stream);

在一个流中,当cudaStreamDestroy被调用时,如果该流中仍有未完成的工作,函数将立即返回,当流中所有工作都已完成时,与流相关的资源将被自动释放。

用以下两个函数检查流中工作是否完成

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

synchronize将阻塞主机,直到给定流中的工作全部完成。query检查流中所有操作是否完成,但不会阻塞,如果完成返回cudaSuccess,未完成返回cudaErrorNotReady。

画个图展示流的作用

for(int i=0; i<nStreams; i++){
    int offset = i * bytesPerStream;
    cudaMemcpyAsync(&d_a[offset], &a[offset], bytesPerStream, streams[i]);
    kernel<<<grid, block, 0, streams[i]>>>(&d_a[offset]);
    cudaMemcpyAsync(&a[offset], &d_a[offset], bytesPerStream, streams[i]);
}

for(int i=0; i<nStreams; i++){
    cudaStreamSynchronize(streams[i]);
}

并发内核的最大数量是依赖设备的。费米架构支持16路并发,开普勒设备支持32路并发。

流调度

从概念上讲,所有流可以并发执行。但是,当流映射到物理硬件时,并不总是这样的。

虚假的依赖关系

虚假的依赖关系(False Dependency)指的是一种由编译器或硬件引入的假象性依赖,导致了代码中不必要的序列化或延迟。这种依赖关系并不反映真实的数据依赖关系,但会影响到代码的执行顺序和性能。

虚假的依赖关系通常出现在对共享内存的操作中,特别是在使用指针进行多次访存的情况下。编译器或硬件可能会认为对同一内存地址的多次访问之间存在依赖关系,从而引入不必要的序列化或延迟。

Hyper-Q技术

Hyper-Q技术使用多个硬件工作队列,减少了虚假的依赖关系。允许多个CPU线程或进程在单一GPU上同时启动工作。

开普勒GPU使用32个工作队列,每个流分配一个工作队列。如果超过32个流,多个流将共享一个硬件工作队列。

流的优先级

计算能力3.5或更高的设备,可以给流分配优先级。优先级高的流的网格队列可以优先占有低优先级流的已经执行的工作。

CUDA事件

CUDA中事件本质上是CUDA流中的标记,它与流内操作中特定点相关联。可以使用事件来执行以下两个基本任务:

  • 同步流的执行
  • 监控设备的进展

CUDA的API提供了在流中任意点插入事件以及查询事件完成的函数。只有当一个给定CUDA流中先前的所有操作都执行结束后,记录在该流内的事件才会起作用(即完成)。

创建和销毁

声明

cudaEvent_t event;

创建

cudaError_t cudaEventCreate(cudaEvent_t* event);

销毁

cudaError_t cudaEventDestroy(cudaEvent event);

记录事件和计算运行时间

事件在流中标记了一个点。可以用来检查正在执行的流操作是否已到达了给定点。

使用如下函数进入CUDA流

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

使用如下函数计算两个事件标记的CUDA操作运行时间

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

返回运行时间,单位为ms。

示例如何进行计时

//创建两个事件
cudaEvent_t start, end;
cudaEventCreate(&start);
cudaEventCreate(&end);

//将开始事件记录在默认流中
cudaEventRecord(start);

kernel<<<>>>();

//将结束事件记录在默认流中
cudaEventRecord(end);

//等待事件结束
cudaEventSynchronize(end);

//计算时间
float time;
cudaEventElapsedTime(&time, start, end);

//释放事件
cudaEventDestroy(start);
cudaEventDestroy(end);

cudaEventSynchronize和stream的相关函数相同。

CUDA流中的事件可以在主机端和设备端都记录。在CUDA中,事件(Event)用于测量时间间隔或同步CUDA流中的操作。主要有以下两种类型的事件:

  1. 主机事件(Host Event):主机事件是由主机代码创建和记录的事件,用于测量主机和设备之间的时间间隔或同步主机代码和CUDA流中的操作。可以使用cudaEventRecord()函数记录主机事件。

  2. 设备事件(Device Event):设备事件是由设备代码(即在CUDA核函数中)创建和记录的事件,用于测量CUDA流中的操作的时间间隔或同步不同的CUDA核函数。可以使用cudaEventRecord()函数在设备代码中记录设备事件。

在使用CUDA流时,通常会在主机端记录主机事件来测量主机与设备之间的时间间隔,同时也可以在设备端使用设备事件来测量CUDA核函数的执行时间或同步不同核函数之间的操作。

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

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

相关文章

【Linux】在Linux中执行命令ifconfig, 报错-bash:ifconfig: command not found解决方案

一、报错信息 ifconfig 报错-bash:ifconfig: command not found 同时&#xff0c;通过ip addr查看&#xff0c;也看不到IP信息 二、解决方案 找到ifcfg-ens0文件&#xff0c;此文件的目录在/etc/sysconfig/network-scripts目录下 命令&#xff1a;cd /etc/sysconfig/network…

Windows系统本地部署DrawDB数据库设计工具并实现无公网IP远程访问

文章目录 1. Windows本地部署DrawDB2. 安装Cpolar内网穿透3. 实现公网访问DrawDB4. 固定DrawDB公网地址 开发中很多时候都会使用到数据库&#xff0c;所以选择一个好用的数据库设计工具会让工作效率翻倍。在当今数字化时代&#xff0c;数据库管理是许多企业和个人项目的核心。设…

buuctf-misc题目练习二

ningen 打开题目后是一张图片&#xff0c;放进winhex里面 发现PK&#xff0c;PK是压缩包ZIP 文件的文件头&#xff0c;下一步是想办法进行分离 Foremost可以依据文件内的文件头和文件尾对一个文件进行分离&#xff0c;或者识别当前的文件是什么文件。比如拓展名被删除、被附加…

Spring - 9 ( 10000 字 Spring 入门级教程 )

一&#xff1a; MyBatis XML 配置文件 Mybatis 的开发有两种方式&#xff1a; 注解XML 我们已经学习了注解的方式, 接下来我们学习 XML 的方式 MyBatis XML 的方式需要以下两步: 配置数据库连接字符串和 MyBatis写持久层代码 1.1 配置连接字符串和 MyBatis 此步骤需要进…

【经验分享】企业网站建设,不收录的原因有哪些

今天来聊一聊我们做好网站&#xff0c;但是网站排名不高&#xff0c;各大搜索引擎不收录网站的原因&#xff1a; 1.网站结构问题&#xff1a; 公司网站的结构是搜索引擎判断网站内容的关键因素之一。如果网站结构混乱、不清晰&#xff0c;搜索引擎可能难以准确抓取和理解网站的…

汇编--栈和寄存器

栈 栈是一种运算受限的线性表&#xff0c;其限定仅在表尾进行插入和删除操作的线性表&#xff0c;表尾也被叫做栈顶。简单概括就是我们对于元素的操作只能够在栈顶进行&#xff0c;也造就了其先进后出的结构特性。 栈 这种内存空间其实本质上有两种操作&#xff1a;将数据放入…

新款iPad Pro引领AI新纪元:M4芯片揭幕,每秒38万亿次运算惊艳业界

新款iPad Pro搭载了强大的M4芯片&#xff0c;拥有每秒高达38万亿次运算的神经处理单元&#xff0c;AI性能超越当今的AI PC。其外观设计更加接近笔记本电脑&#xff0c;展示了苹果对AI技术的全面拥抱。此次发布不仅是对iPad Pro的一次重大更新&#xff0c;更是为下个月的WWDC发布…

00后抛弃新氧、上游抗议低价,金星又被打脸了

作为“颜值焦虑”的受益者&#xff0c;新氧也面临自己的焦虑。 据新氧最近发布的年报&#xff0c;2023年营收14.98亿元&#xff0c;同比增长19.1%&#xff1b;净利2130万元&#xff0c;同比扭亏为盈。但是&#xff0c;这仅是源于2022年公司业绩的低基数对比&#xff0c;并不能…

Faiss核心解析:提升推荐系统的利器【AI写作免费】

首先&#xff0c;这篇文章是基于笔尖AI写作进行文章创作的&#xff0c;喜欢的宝子&#xff0c;也可以去体验下&#xff0c;解放双手&#xff0c;上班直接摸鱼~ 按照惯例&#xff0c;先介绍下这款笔尖AI写作&#xff0c;宝子也可以直接下滑跳过看正文~ 笔尖Ai写作&#xff1a;…

QT---day4事件

1、思维导图 2、 头文件 #ifndef MYWIDGET_H #define MYWIDGET_H #include <QWidget> #include<QIcon> //图标类 #include<QLabel> //标签类 #include<QMovie> //动图类 #include<QLineEdit> //行编辑器类 #include<QPushButton> //按钮…

MATLAB 自定义实现点云随机抽稀方法(66)

MATLAB 自定义实现点云随机抽稀方法(66) 一、算法介绍二、算法实现1.代码2.结果三、数据链接一、算法介绍 MATLAB虽然提供了点云随机抽稀的内置函数,但是我们也可以自己实现这个功能,有助于理解,下面是具体的实现效果和代码(直接复制粘贴即可使用): 使用提供的数据直接…

企业计算机服务器中了rmallox勒索病毒怎么破解,rmallox勒索病毒解密工具步骤

科技技术的发展&#xff0c;为企业的生产运营注入了新的活力&#xff0c;越来越多的企业利用网络走向了数字化办公模式&#xff0c;网络也极大地方便了企业的生产运营&#xff0c;大大提高了企业的生产效率&#xff0c;加快了企业发展的步伐。但是网络数据安全问题一直是企业关…

图片公式识别@文档公式识别@表格识别@在线和离线OCR工具

文章目录 abstract普通文字识别本地软件识别公式扩展插件下载小结 在线识别网站/API&#x1f47a;Quicker整合(推荐)可视化编辑和识别公式其他多模态大模型识别图片中的公式排版 开源模型 abstract 本文介绍免费图片文本识别(OCR)工具,包括普通文字识别,公式识别,甚至是手写公…

vue使用screenfull实现全屏模式

vue实现全屏模式可以通过第三方依赖screenfull完成效果。 实现效果&#xff1a;查看源码 首先需要安装第三方依赖 // npm npm install screenfull//yarn yarn add screenfull// pnpm pnpm install screenfull代码实现&#xff1a; <div class"flex-center w100 h…

go导入包时提示no required module provides package解决方法

原因&#xff0c;这个包在你的本机没有安装 如redis包的提示为 could not import github.com/gomodule/redigo/redis (no required module provides package "github.com/gomodule/redigo/redis")解决方法&#xff1a; go get github.com/gomodule/redigo/redis

无人机+光电吊舱:四光(可见光+红外热成像+广角+激光测距)吊舱设计技术详解

无人机与光电吊舱的结合&#xff0c;特别是四光吊舱&#xff08;包含可见光、红外热成像、广角和激光测距技术&#xff09;的应用&#xff0c;为无人机提供了强大的侦察和测量能力。以下是对四光吊舱设计技术的详解&#xff1a; 1. 可见光技术&#xff1a;可见光相机是吊舱中最…

C++:编程界的王者,引领未来的创新之路

在编程语言的浩瀚星空中&#xff0c;C犹如一颗耀眼的恒星&#xff0c;以其卓越的性能、深厚的底蕴和广泛的应用领域&#xff0c;持续引领着编程界的发展。它不仅在当下拥有无可替代的地位&#xff0c;更在未来展现出无限的潜力和可能性。 一、C&#xff1a;编程界的王者风范 …

基于JSP动漫论坛的设计与实现(二)

目录 3. 系统开发环境及技术介绍 3.1 开发环境 3.2 开发工具 3.2.1 MyEclipse8.5 3.2.2 MySql 3.3 相关技术介绍 3.3.1 JSP技术简介 3.3.2 JDBC技术技术简介 3.3.3 MVC模式与Struts框架技术 4. 总体设计 4.1 系统模块总体设计 4.1.1 普通用户模块设计 4…

将要上市的自动驾驶新书《自动驾驶系统开发》中摘录各章片段 4

第十三章 车联网 数字化设备正变得越来越普遍并且相互联系。这些设备向数字生态系统智能部分的演进创造了迄今为止尚未解决安全问题的新颖应用。一个特定的例子是车辆&#xff0c;随着车辆从简单的交通方式发展到具有新的感知和通讯功能的智能实体&#xff0c;就成为智能城市的…

免费思维13招之二:第三方思维

思维02:第三方思维 第三方思维又叫第三方资费思维。是一种可以使你的产品免费但是你却依然赚钱的思维。 大家还记得之前讲的“餐厅免费吃饭却年赚百万”的案例吗?这个案例运用了多种免费思维的子思维,其中也用到了第三方资费思维,怎么运用的呢?韩女士,与各行各业合作,…