Vulkan 同步

news2024/10/5 18:30:38

前言

在前面的文章中,我们讲解了Vulkan的多线程设计理念,分析了其底层的机制。我们知道在Vulkan的设计中,尽量避免资源的同步竞争,但是在某些复杂场景和多线程优化过程中难免会遇到资源竞争的问题,这时候就需要同步机制来保证线程访问数据的安全性和一致性。

然而Vulkan认为资源读写所需要做的同步是应用程序的职责,其内部只提供了很少的隐式同步机制,其余的都需要在程序中显式地使用Vulkan中的同步机制来实现。

Vulkan同步基础

在Vulkan代码实现中,使用的同步命令会涉及如下代码:

VkPipelineStageFlags

Vulkan所有的命令都会在Pipeline上执行,只是不同类型的命令,它们的执行阶段是不同的。当我们在Vulkan中使用同步机制时,都是以流水线阶段为单位,即某个流水线阶段上执行的所有命令,会在当前阶段暂停,等待另一个流水线阶段上的所有命令在相应的阶段执行完全后,再开始执行。VkPipelineStageFlags就代表流水线阶段。

VkAccessFlags

Vulkan中的同步不仅控制操作执行的顺序,还要控制缓存的写回,即内存数据的同步,VkAccessFlags是为了控制流水线阶段对于内存的读写操作。

因为在CPU等存储器件为了读写性能都会分为多层缓存。多级缓存就会导致多线程读写数据的一致性问题,就需要有机制保证某一层缓存数据更新了需要同步到其他缓存上,比如MemoryBarrier,而所有的MemoryBarrier中也都会包含VkAccessFlags参数。

Vulkan所有的同步在全局上都应该认为是对一个Queue中的所有命令有效果。

Vulkan同步原语

Vulkan中主要有四种同步原语(synchronization primitives):

  •  Fences
    • 最粗粒度的同步原语,用于同步跨队列或跨粗粒度提交到单个队列的工作,目的是给CPU端提供一种方法,可以知道GPU或者其他Vulkan Device什么时候把提交的工作全部做完。类似Android的显示机制。

  • Semaphores

    • 颗粒度比Fences更小一点,通常用于不同Queue之间的数据同步操作

  • Events

    • 颗粒度更小,可以用于Command Buffer之间的同步工作。

  • Barriers

    • Vulkan流水线(Pipeline)阶段内用于内存访问管理和资源状态移动的同步机制。

Fence

如上介绍Fence是粗粒度的同步,它有两种状态——signaled和unsignaled。

在调用vkQueueSubmit时可以关联一个Fence,这样当Queue中的所有命令都被完成以后,Fence就会被设置成signaled的状态;

通过调用vKResetFences可以让一个Fence恢复成unsignaled的状态;

vkWaitForFences会让CPU原地阻塞,需要等待直到它关联的Fence变为signaled的状态,这样就可以实现在某个渲染队列内的所有任务被完成后,CPU再执行某些操作的同步场景。

Fence也具备内存数据同步的功能,但不需要开发者手动调用。在使用Fence时,如果它一旦被设置成signaled状态,那么使用这个Fence的Queue中的所有的命令如果涉及到了对内存的修改,后续的内存访问就一定会在signaled之前在Device上更新(注意只是在Device上更新,如果确保CPU也能够获取最新的值的话,就需要再用上其他的同步原语)。

Semaphore

Semaphore用于queue每次提交的一批命令之间的同步和Fence一样,它也有两种状态:signaled和unsignaled。

调用vkQueueSubmit提交命令时,会填充VkSubmitInfo结构,而这个结构体中需要设置pWaitSemaphores、pSignalSemaphores、pWaitDstStageMask。程序在执行到pWaitDstStageMask时要阻塞,直到等pWaitSemaphores所指向的所有Semaphore的状态变成signaled时才可以继续执行。本次提交的Command buffer执行结束后,pSignalSemaphores所指向的所有Semaphore的状态都会被设置成signaled。

注:vkQueueSubmit函数本身也隐含了一个内存数据的同步机制:就是CPU上所有的内存修改操作,都会在GPU读写之前,对GPU而言变成available的,并且对于所有后续在GPU上的MemoryAccess,它们都是visible的。

部分相关代码示例:

vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame]);

Event

Event同样也具有两种状态——signaled和unsignaled,与Fence不同的是,它的状态改变既可以在CPU上完成,也可以在GPU上完成,并且它是一种细粒度的同步机制。注意:Event只能用在同队列的Command buffer间的同步。

在CPU侧可以调用vkSetEvent来使一个Event变成Signaled的状态;调用vkResetEvent来使一个Event恢复成Unsignaled的状态;调用vkGetEventStatus获取一个Event的当前状态,根据Event状态阻塞CPU运行。

GPU侧:通过vkCmdSetEvent命令来使得一个Event变成Signaled状态,此时该命令附加了一个操作执行同步:根据提交顺序,在该命令之前的所有命令都必须在Event设置Signaled状态之前完成。

通过vkCmdResetEvent命令来使得一个Event变成Unsignaled状态,此时该命令同样附加了一个操作执行同步:根据提交顺序,在该命令之前的所有命令都必须在Event设置Unsignaled状态之前完成。

相关代码:

Barrier

所有的同步原语中,Barrier的使用成本最高。Barrier用于显式地控制buffer或者image的访问范围,避免hazards(RaW,WaR,and WaW),保证数据一致性。

Barrier又分为pipeline barrier和memory barrier。

pipeline barrier

要开发者了解渲染管线的各个阶段,能清晰地把握管线中每个步骤对资源的读写顺序。

Vulkan中Pipline各阶段的定义:

  • TOP_OF_PIPE_BIT
  • DRAW_INDIRECT_BIT

  • VERTEX_INPUT_BIT

  • VERTEX_SHADER_BIT

  • TESSELLATION_CONTROL_SHADER_BIT

  • TESSELLATION_EVALUATION_SHADER_BIT

  • GEOMETRY_SHADER_BIT

  • FRAGMENT_SHADER_BIT

  • EARLY_FRAGMENT_TESTS_BIT

  • LATE_FRAGMENT_TESTS_BIT

  • COLOR_ATTACHMENT_OUTPUT_BIT

  • TRANSFER_BIT

  • COMPUTE_SHADER_BIT

  • BOTTOM_OF_PIPE_BIT

举一个简单的例子:

场景中有两个渲染管线P1 和 P2,P1会通过Vertex Shader往Command buffer写入顶点数据,P2需要在Compute Shader中使用这些数据。如果使用fence,P1的command提交后,P2通过fence确保P1的操作已经被全部执行完,再开始工作。但理论上P2只需要在Compute Shader阶段等待P1的顶点数据即可。

该场景优化可以用Barrier,只需要告诉Vulkan,我们在P2的Compute Shader阶段才需要等待P1 Vertex Shader里面的数据,其他阶段可以并行。

Memory Barrier

内存数据的同步需要使用Memory Barrier完成,Vulkan中有三种MemoryBarrier。

所有的MemoryBarrier都需要搭配PipelineBarrier或者Event使用。

隐藏的执行顺序

Vulkan是显式的,号称“没有秘密的API”。但是在多线程同步时,还是存在一些潜规则。在提隐式执行前,先来了解下提交顺序,它是Vulkan的隐式同步及用户的显式同步的前提。

  • 在CPU上通过多次vkQueueSubmit提交了一系列命令,这些命令的提交顺序为先提交的先行。
  • 同一个Queue中,一起提交的多个Command Buffer,按照下标顺序提交。

  • 同一个Command Buffer的操作,先提交的先行

了解了提交顺序后,我们来看下Vulkan中隐式的执行顺序,

  • Command Buffer中的Command,严格遵循提交顺序的,先记录的先执行。
  • ImageLayout的转移是通过ImageMemoryBarrier实现的,严格按照提交顺序执行。

  • 同一个Queue中,一起提交的多个Command Buffer,严格按照提交顺序执行

  • 先提交的Command Buffer先执行

总结

本篇文章讲了Vulkan中的同步机制,包含显示和隐藏的同步控制,只能感叹Vulkan的操作是真的繁琐,希望大家能在了解同步机制的情况下,实现出性能更极致的程序。

参考

Vulkan Specification

Yet another blog explaining Vulkan synchronization

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

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

相关文章

Redis实战案例19-Redis解决主从一致性问题

主节点(Master)“写操作”: 接收并响应客户端的读写请求。持久化数据到磁盘(根据配置可以选择使用RDB快照或者AOF日志)。将自己的写操作同步给所有的从节点。处理发布/订阅(Pub/Sub)模式中的发…

shell脚本备份数据库

首先是在本地windows环境下尝试备份数据库 打开mysql的bin目录,然后在地址栏cmd,进入cmd界面,输入mysqldump命令,-u输入用户名,-p输入密码 还有数据库名称,以及后面要保存到的位置 mysqldump -uroot -p tes…

数据标准化助力生产企业产能提升

毫无疑问,多产线、多工厂的协同管理成为集团构建核心竞争力的关键因素。企业内部供应链、研制链的业务贯通与协作需要基于统一的数据标准、统一的集成规范开展,数据标准化将成为企业数字化转型的有效赋能手段。 一、客户诉求 近年来,随着国…

OpenAI科学家Jason Wei关于人工智能的回复

问:你的人工智能之路是如何开始的? 答:虽然你们知道我的工作可能是从 2022 年开始的,但我从 2017 年就开始从事人工智能工作了。在达特茅斯大学读本科时,我原本想成为华尔街的一名银行家,这是我父母那一代…

ORAN上行帧和下行帧的定时关系

在UE天线端口处,相同帧号的UL无线帧,相对于DL无线帧有定时提前偏移。N_TA offset是应用于UE的默认定时偏移参数,除非根据3GPP 36.211或38.211中规定,在小区中配置了另一个值。n-ta-offset是M平面参数,用于控制在O-RU天…

软件设置开机自启

文章目录 一、使用系统自带工具设置开机启动1.winR键打开运行窗口2.输入"shell:startup"→点击确定3.将要开机自启的软件快捷方式放到启动目录下就行 一、使用系统自带工具设置开机启动 1.winR键打开运行窗口 2.输入"shell:startup"→点击确定 3.将要开机…

FastEdit ⚡:在10秒内编辑大型语言模型

概述: 这个仓库旨在通过一个单一的命令,有效地将新鲜且定制化的知识注入到大型语言模型中,以辅助开发人员的工作。 支持的模型:○ GPT-J (6B)○ LLaMA (7B/13B)○ BLOOM (7.1B)○ Falcon (7B)○ Baichuan (7B/13B)○ InternLM (7…

【es】部署后打不开访问页面

具体报错: [2023-07-18T00:55:28,203][WARN ][o.e.x.s.t.n.SecurityNetty4HttpServerTransport] [demo] received plaintext http traffic on an https channel, closing connection Netty4HttpChannel{localAddress/127.0.0.1:9200, remoteAddress/127.0.0.1:5529…

企业应如何面对数字化时代?

企业要想有效面对数字时代,就需要适应和拥抱数字技术带来的机遇和挑战。以下是企业需要考虑的一些关键策略: 拥抱数字化转型:数字化转型涉及重新思考和重新构想业务流程、产品和服务以利用数字技术。这可能包括自动化流程、采用云计算、实施数…

如何学习Java集合框架? - 易智编译EaseEditing

要学习Java集合框架相关的技术和知识,可以按照以下步骤进行: 掌握Java基础知识: 在学习集合框架之前,确保你已经具备良好的Java编程基础,包括语法、面向对象编程(OOP)原理和常用的核心类库等。…

HIVE SQL几种不同的分组排序函数比较

--数据建表 drop table if exists db.tb_name; create table if not exists db.tb_name ( name string,class string,score string ) ; insert overwrite table db.tb_name values ("a","1","100") ,("b","1","99"…

pdf怎么转换成TXT格式?分享这3个方法!

当我们需要从PDF文件中提取文本时,尤其是在收集资料撰写文章或其他文件时,PDF文件的特性可能会造成一些麻烦。PDF文件的版面内容不会受浏览设备的影响,保持着统一的版式,但同时也不易于编辑和修改。因此,常见的解决方案…

基于SSM+Vue的汉服文化平台网站设计与实现

博主介绍: 大家好,我是一名在Java圈混迹十余年的程序员,精通Java编程语言,同时也熟练掌握微信小程序、Python和Android等技术,能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…

CleanMyMac X2023中文版升级下载及功能讲解

CleanMyMac X是一款功能强大的Mac系统优化和清理工具。它提供了一系列功能来帮助您优化和保护您的Mac电脑。coco玛奇朵要来分享的是Mac下一款强大、实用的系统清理软件——CleanMyMac,它可以帮助您快速清理系统垃圾,清理Photos重复照片,卸载软…

仿大众点评项目 —— 各阶段详细笔记总结

❤ 作者主页:欢迎来到我的技术博客😎 ❀ 个人介绍:大家好,本人热衷于Java后端开发,欢迎来交流学习哦!( ̄▽ ̄)~* 🍊 如果文章对您有帮助,记得关注、点赞、收藏、…

【MySQL】MySQL8.1.0版本正式发布带来哪些新特性?

文章目录 前言一、畅谈新版本二、8.1.0版本部署2.1、环境准备2.2、配置yum安装依赖2.3、用户及目录创建2.4、创建用户及组2.5、解压缩包2.6、环境变量配置2.7、创建参数文件2.8、数据库初始化2.9、启动Mysql2.10、登陆MySQL 8.1 三、新特性3.1、密码参数3.2、错误日志加强3.3、…

第三章:内存

一、内存的基础知识二、内存管理的概念2.1 **内存空间的扩充技术**2.2 内存空间的分配与回收2.2.1 连续分配管理方式2.2.2 动态分区分配算法2.2.3 非连续分配管理方式2.2.3.1 **基本分页存储管理**2.2.3.2 基本地址变换结构2.2.3.3 具有快表的地址变换机构2.2.3.4 俩级页表2.2.…

使用更少数据训练更好的alpaca

概述 该论文的研究背景是指令微调在大型语言模型中取得了重要的成果,但现有的训练数据质量问题导致模型性能下降。 过去的方法主要是使用低质量的数据进行指令微调,这些数据中存在错误或无关的回答,导致结果误导和训练成本增加。该论文的方…

赫达转债,明电转02上市价格预测

赫达转债 基本信息 转债名称:赫达转债,评级:AA-,发行规模:6.0亿元。 正股名称:山东赫达,今日收盘价:18.72元,转股价格:17.4元。 当前转股价值 转债面值 / 转…

代码测试工具Fortify最新版本介绍及实操

代码测试工具是安全测试、代码审计中经常会用到的一款软件测试工具,支持超过27种语言,超过911,000个组件级API,覆盖810多个SAST漏洞分类。通过Fortify的安全编码规则库,可以定位漏洞根本原因,参考漏洞修复指南。Fortif…