0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Vulkan图形处理过程中遇到的问题

Dbwd_Imgtec 来源:Imagination Tech 作者:Imagination Tech 2020-09-04 11:45 次阅读

利用乒乓机制的交错队列减少风险

在本篇文章中,我们将提到Vulkan 图形处理过程中夹杂计算任务时遇到的各式问题。为更准确地了解我们的话题,可查看文章第一部分。

第一部分概述了在Vulkan中如何使用barrier;具体来说,涉及图形→计算barrier,随后是一个中间帧计算→图形barrier。这会严重削弱GPU任务调度能力,并导致暂停,降低性能。为此我们给出了在多种资源配置情况下的不同解决方案。

体系架构级方法

"算法"优先的方法是手动使任务交错:也就是说,以我们希望的顺序提交任务,并使它们在GPU 上执行。这会生成正确结果,也为我们提供足够的可控性。在该情况下,首先为上一"逻辑"帧提交计算任务BN-1(注意缺少早期图形任务),然后提交当前帧AN的早期图形任务。随后,将提交计算/图形Barrier,接下来提交上一帧CN-1的后期图形任务,最后提交图形/计算Barrier。

这种方法会产生良好的结果,但会有损帧分离性,使维护更加困难。它对逻辑资源的需求将加倍,因为至少部分后期帧的操作代码需要比早期帧操作先调度。此外,会引入一个额外的滞后帧。 其执行过程如下: 帧N: BN-1→AN→ 计算/图形barrier→CN-1→图形/计算barrier→提交N-1 帧N+1: BN→ AN+1→ 计算/图形barrier→CN→图形/计算barrier→提交N 这将允许BN-1/AN重叠。 听起来很复杂,而且也确实如此:计算多个帧操作通常需要大量的记录。但是,如果在此方案中任务封装的不错,至少一定程度上会缓解该问题。但是,如果复杂性更高时(即更复杂的猜测计算→barrier→图形→barrier→计算→barrier→图形工作负载),它仍然可能崩溃。在任何情况下,为降低不断增加的CPU 端复杂性成本,可以定制解决方案。

每个任务使用不同队列

另一个有效的解决方案是使用不同的队列,并在每个队列提交帧的不同部分:每个早期计算、后期计算、早期图形和后期图形提交到自己的队列,任务间连接使用信号量而非barrier。例如 ,PowerVR开发套件中的Vulkan粒子系统就是采用该方法,在对应的专用队列中提交所有计算。

但在我看来,该方案有其挑战性,它比交错帧更好,因为它允许 GPU 处理自己的问题,而不会弄乱引擎的非 API 部分。在我看来,它也是第一个"真正的"解决方案。类似于上述方案,它至少会缓解部分问题。在讨论其自身体系结构上的计算后处理时,Arm 在其社区网站上也将目光投向该方案。但是,它又取决于某些特定任务的重叠,一般来说,需要仔细生成大量的信号量,并且借助于队列优先级,这些增加了部分复杂性,但也为您提供了另一个控制向量。在多个交错计算/图形任务的情况下,它也可能不能完全按照我们预期的方式工作。该方案非常有效,可能将其与别的方案结合是个好思路。 我们已经找到了值得推荐的不同方案。

更简单、通用的方案:乒乓机制的交错队列

我们相信我们可以更简单、更有效的方式来完成计算。为此,我们需要从全局上考虑我们的最终目标:我们需要在没有Vulkan 规范介入的前提下,使 GPU 能够在连续两个帧中交替工作。

Vulkan 规范团队中的精明者可能已经意识到,barrier是始终指向单个队列的构造器。 PowerVR(和许多其它设备)设备可能会暴露多个相同/可互换的通用队列(图形+计算以及可能的呈现)。 因此,在这种情况下,为在不重新调整帧前提下避免跨帧同步,我们可以在不同队列中为每个帧提交负载。这将允许一个帧中的任何负载与下一帧中的任何负载交错执行,即使具有多个不同的图形、顶点和计算任务,因为它们在不同队列上显式执行,可以不受制于彼此的barrier。 简单来说:从同一队列源中创建两个相同的队列,然后对于每个帧,您提交负载到与上一队列不同的队列上。队列源很重要,因为它可以使您不必担心资源队列所有权等问题。 因此,帧提交过程如下: 帧 0:获取下一个图像→渲染 0(A0)→图形/计算barrier→计算0(B0)→计算/图形barrier→渲染0′(C0)→提交到队列0 →呈现到队列 0 帧 1:获取下一个图像→渲染 1A1→图形/计算barrier→计算1B1→计算/图形barrier→渲染1′C1→提交到队列1→呈现到队列1 帧 2:获取下一个图像→渲染2 A2→图形/计算barrier→计算2B2→计算/图形barrier→渲染2′C2→提交到队列0 →呈现到队列 0 帧 3:获取下一个图像→渲染 3A3→图形/计算barrier→计算3B3→计算/图形barrier→渲染3′C3→提交到队列1→呈现到队列1 ...等等。 那么,这行得通吗?而且,如果可以,其原因是什么? 确实可行。BN(当前帧计算)和 CN(当前帧的后期图形)之间的barrier将阻止 CN在BN完成之前启动,但不会阻止 AN+1(下一帧的早期图形)启动,因为它在与Barrier不同的队列上提交(一个额外的好处,由于队列不同,AN+1与CN不需要强制排序)。 此技术解决了问题的核心:应用程序设置的barrier,旨在在单个帧中等待风险的发生,不会导致后续帧之间的任务间等待。我发现它相当令人欣喜,而且是迄今为止最简单的可实现方案——只要您的通用队列源中有多个队列,就可以使用单个计数器(甚至是布尔类型)并交换每一帧,此时无需进一步修改:只要我们确保 CPU 资源得到正确管理(与单个队列相同),不须施加额外同步。 简而言之,由于每个连续帧都在不同的队列中提交,因此 GPU 可以自由地在帧之间并行调度任务,预期结果为 (CN+1) 在(AN) 完成之后开始执行。它可确保渲染器及其相应的调度程序始终繁忙,并且中间的计算不会串行化帧。 —————– 计算工作负载:B0B1 B2B3 B4B5 图形工作负载:A0 A1 C0 C1 A2 A3 C2 C3 A4 A5 C4 C5 ... 或(基本相同的效果)如下: 计算工作负载:B0 B1 B2 B3 B4 B5 图形工作负载:A0 A1 C0 A2 C1 A3 C2 A4 C3 A5 C4 C5 ...

解决方案:通过使用多个队列,可以在上一帧的早期任务之后安排下一帧的早期片段任务,与计算任务重叠以获得出色的效率增益 乍一看,这看起来可能很复杂,但实际很简单。无论如何,该图示告诉我们,GPU 正在处理一个帧(N)的计算,同时处理下一帧 (N+1) 的早期图形或上一帧的后期图形。

完全封装的情况是"相当不可能",它甚至没有必要达到这种水平的封装。但是,您应具备类似的特征,计算与顶点/片段任务一起调度,允许USC 加载使用尽可能多的容量。

其他的适用方案

通常,在任何存在barrier的情况下(而不仅仅是图形/计算/图形)时使用此技术是一个好思路。在任何情况下,它都不会有损性能,并且在--任何情况下调度器都具备更好的灵活性。调度器可能不需要额外的灵活性,但在任何情况下它都不会有损性能,而且增加的复杂性微不足道。

任何类型的barrier(包括图形/图形)都有可能损害 GPU 调度不同帧负载的能力并会导致暂停(顺便说一下,这是考虑使用barrier一个非常重要的原因,如果不考虑该因素,可以使用子类依赖性而非barrier)。计算示例非常重要,因为即使它们共享 PowerVR 上的执行内核、图形和计算部件,它们也在不同的数据主设备上工作,因此始终有些任务要并行执行,因此,如果可能,我们总是希望它们尽量重叠工作。但是,即使只是不同帧的图形负载交错执行,也通常允许您在顶点和片段任务之间获得更多的重叠,并确保 GPU 更好的饱和性。

因此,任何barrier情况都存在潜在风险,所以使用多个队列是备选。

注意事项:如何采用交错队列防止乱序

我们未能发现任何严重的不利条件。在不同帧之间使用不同的队列没有额外开销。我们确定的唯一限制很明显:同一队列源必须支持多个图形计算队列,不过,所有 PowerVR 设备都支持该特性。

我们能够识别的另一潜在问题是确保正确的呈现顺序。但是,交换链对象本身将确保这一点,因为图像以 FIFO 和邮箱呈现模式调用的 vkQueuePresent 顺序呈现。对于其它模式(例如即时),您可能需要确保当前操作正确同步,以便按顺序执行; 这也相当容易实现。 最后,如果设备强制采用单个呈现队列,您可以修改如下,最终只在单个队列上呈现: 帧 0:获取下一个图像→渲染 0→记录图形/计算barrier→计算0 →计算/图形barrier→渲染0′→提交到队列0 →呈现到队列 0 帧 1:获取下一个图像→渲染 1→记录图形/计算barrier→计算1→计算/图形barrier→渲染1′→提交到队列1 →呈现到队列0 帧 2:获取下一个图像→渲染2→记录图形/计算barrier→计算2→计算/图形barrier→渲染2′→提交到队列0 →呈现到队列 0 帧 3:获取下一个图像→渲染 3→记录图形/计算barrier→计算3→计算/图形barrier→渲染3′→提交到队列1 →呈现到队列0 ...等等。 它不仅利用了并行性,还确保了具有交换链"特殊"实现的驱动程序不会出现乱序帧呈现的风险。 简言之,我们完全可以放心的使用该技术。如果你发现了潜在的问题,请告诉我们。重要性能说明

需要提醒的是,PowerVR 调度时与 CPU 线程调度工作方式不同,因为后者需要昂贵的上下文切换并保存到主存——如果调度器在同一 USC 上并行执行两个任务,在大多数情况下,它们之间切换成本为零,因此每当需要等待操作时(例如内存访问),调度器都可以切换到另一个任务并隐藏内存操作延迟。这是我们性能得以提升的重要部分。

下面是我们需要澄清的:该技术主要不是填充可能出现空闲的不同硬件部分负载,我们试图做的是指导驱动程序正确调度负载,减少开销并隐藏延迟。PowerVR 是一个统一的体系结构,顶点、图形和计算任务都在同一个 USC 上执行。与在不同顶点和片段着色器内核单独执行的早期图形设备不同,100%性能提升是无法实现的。我们不是要填充空闲内核;只是要 GPU非空闲时, 所有USC 都在运行(不排除一些意外状况发生)。 最后,在仅有图形的负载中,还可能会遇到这样的情况,barrier会阻止不同帧之间的重叠。

未来工作

当您希望将不同的任务提交到不同的队列类型/源情况下,此技术可以而且将起作用。一个重要的免责声明是,该技术不会取代帧的不同负载使用不同队列的潜在好处——如本文及其他文章中所讨论到的,使用不同的专用队列(特别是使用不同的队列优先级来最小化帧延迟)。

因此,在这些情况下,可以使用相同的逻辑——唯一的区别是,您不会将一个队列分裂为两个队列,而是将所有(或大多数)使用barrier的队列复用。这可能并非所有队列,因此不能替代常识和良好设计。在某些体系结构中,您可能使用三个不同的队列,并且只需要将其中一个或者多个中的两个队列复用并进行乒乓操作。最重要的是在barrier旁边至少增加一个队列。 例如,假设一个专用计算队列与多个通用队列并存,此技术可能仍然有用。事实上,在多数的有趣场景下,拥有多组具有不同优先级的不同队列并且帧之间交换集,这可以提供惊人的精细控制和灵活性。 这种情况可能工作如下: (此处的队列 C2 是一个专用计算队列,队列 0 和队列 1 是我们要复用的通用队列): 帧 0:获取下一个图像→渲染 0 →提交到队列 0 →信号量给队列 2 →计算 0,提交到队列 C2→信号量给队列 0 →渲染0′→提交到队列 0→呈现给队列 0 帧1:获取下一个图像→渲染1→提交到队列 1→信号量给队列 2→计算 1,提交到队列 C2→信号量给队列 1→渲染1′→提交到队列 1→呈现给队列 1 帧2:获取下一个图像→渲染2→提交到队列 0 →信号量给队列 2 →计算 2,提交到队列 C2→信号量给队列 0 →渲染2′→提交到队列 0→呈现给队列 0 帧 3:获取下一个图像→渲染3→提交到队列1→信号量给队列 2 →计算 3,提交到队列 C2→信号量给队列 1→渲染3′→提交到队列 1→呈现给队列 1 帧 4:获取下一个图像→渲染4→提交到队列 0 →信号量给队列 2 →计算 4,提交到队列 C2→信号量给队列 0 →渲染4′→提交到队列 0→呈现给队列 0

同样,此处的多个图形队列是必要的,以允许在当前帧的第二次渲染之前调度连续帧的第一次渲染。

结论

我们向您展现了一个非常完整和通用的解决方案,用以解决常见但现实的难题。无论何时,尽可能为每帧使用多个队列,您可以无风险、更简单地获得惊人的性能提升。希望这将对您的项目有帮助!如果该技术确实帮助到您,欢迎向我们分享您的故事。

我们在 PowerVR SDK中的许多演示中都使用此技术,而且我们在编写后处理演示时也受到了启发,并使用了该技术。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • cpu
    cpu
    +关注

    关注

    68

    文章

    10824

    浏览量

    211088
  • 图形处理
    +关注

    关注

    0

    文章

    43

    浏览量

    13768
  • Vulkan
    +关注

    关注

    0

    文章

    28

    浏览量

    5701

原文标题:Vulkan同步机制和图形-计算-图形转换的风险(二)

文章出处:【微信号:Imgtec,微信公众号:Imagination Tech】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    使用ADS1299的过程中遇到的疑问求解

    我在使用ADS1299的过程中有一点疑问,需要您的帮助。 这是一张关于BIAS反馈回路的示意图,在我的理解里这可以看作一个加减运算电路,我想知道的是,只关注它的反向输入时,且暂时忽略1.5nF的电容,外部只加1M的电阻,它的放大倍数是多少? 期待您的回复!
    发表于 11-15 06:35

    SMT组装过程中缺陷类型及处理

    表面贴装技术(SMT)是现代电子制造业的关键环节,它通过自动化设备将电子元件精确地放置在PCB上。尽管SMT技术已经相当成熟,但在组装过程中仍然可能出现各种缺陷。 一、焊膏印刷缺陷 焊膏量不足或
    的头像 发表于 11-14 09:25 269次阅读

    使用VCA810过程中遇到的一些问题求解

    我在使用VCA810过程中遇到一些问题,请各位大神指点,具体如下: 1、控制电压最小只能加到-1.7V,再减小的话输出信号消失或者放大倍数骤然减小。 2、输入端出现一个叠加在信号上的直流,输出端直
    发表于 08-30 07:11

    PLC对模拟量信号的处理过程及方法 详解版

    )。 PLC通过计算转换,将这些模拟量信号转换为内部的数值信号。从而实现系统的监控及控制。从现场的物理信号到PLC内部处理的数值信号,有以下几个步骤: 从以上PLC模拟量的信号输入流程可以看到,在自动化过程控制系统,模拟量信号
    的头像 发表于 07-30 16:31 333次阅读
    PLC对模拟量信号的<b class='flag-5'>处理过程</b>及方法 详解版

    电容充放电过程中电压的变化规律

    电容充放电过程中电压的变化规律是一个非常重要的电子学课题,涉及到电容器的基本工作原理和特性。在这篇文章,我们将详细探讨电容充放电过程中电压的变化规律,包括电容的基本特性、充电过程、放
    的头像 发表于 07-11 09:43 4299次阅读

    使用PSoC5LP的过程中,遇到PSoC5LP在EFT干扰时复位的问题怎么解决?

    在我使用 PSoC5LP 的过程中(>8 年),我曾多次在验证测试遇到 PSoC5LP 在 EFT 干扰时复位的问题。 大多数情况下,这取决于 XRES 引脚,因为 EFT 可以改变
    发表于 07-05 07:26

    连焊如何在SMT加工过程中发生的?

    在电子制造业,SMT加工是一项复杂且需要高精度的技术活动。在这个过程中,连焊是一个常见但严重的问题,它可能破坏整个电路板的性能和稳定性。作为专业的深圳佳金源锡膏厂家,对于很多客户遇到连焊
    的头像 发表于 05-14 16:20 290次阅读
    连焊如何在SMT加工<b class='flag-5'>过程中</b>发生的?

    IGBT模块封装过程中的技术详解

    IGBT 模块封装采用了胶体隔离技术,防止运行过程中发生爆炸;第二是电极结构采用了弹簧结构,可以缓解安装过程中对基板上形成开裂,造成基板的裂纹;第三是对底板进行加工设计,使底板与散热器紧密接触,提高了模块的热循环能力。
    发表于 04-02 11:12 1078次阅读
    IGBT模块封装<b class='flag-5'>过程中</b>的技术详解

    smt加工过程中空洞产生的原因及处理方法

    SMT加工过程中,有时会出现空洞的情况,这会影响产品的质量和性能。接下来深圳PCBA加工厂家将对SMT加工过程中空洞产生的原因进行详细分析,并探讨相应的解决方案。 首先,让我们来了解一下SMT加工的基本流程和原理。SMT加工主要分为三个步骤:印刷
    的头像 发表于 04-02 09:40 560次阅读

    陶瓷电熔炉启动过程中升温停止问题的原因及解决办法分析

    放射性废物的处置问题一直是核工业发展过程中不可忽视的关键环节。核燃料后处理循环过程中产生的高放废液的安全处置是放射性废物处理的关键,国际上比较成熟的高放废液
    的头像 发表于 03-12 16:43 614次阅读
    陶瓷电熔炉启动<b class='flag-5'>过程中</b>升温停止问题的原因及解决办法分析

    ADC处理过程中的各个步骤

    在现实世界,模拟信号具有不断变化的值,这些值来自各种来源和传感器,可以测量声音,光,温度或运动,许多数字系统通过测量来自这些传感器的模拟信号与环境相互作用。
    的头像 发表于 01-23 16:46 2826次阅读
    ADC<b class='flag-5'>处理过程中</b>的各个步骤

    使用ADXL362的过程中遇到了ODR不准确的问题怎么解决?

    在使用ADXL362的过程中遇到了ODR不准确的问题,具体为: 1、3V电源供电,系统设置ADXL362 ODR为50Hz,采用FIFO Triggered Mode模式,64个点的FIFO
    发表于 12-29 07:05

    电容充放电过程中时间常数对电路的影响

    电容充放电过程中的时间常数对电路有着重要影响。时间常数是指电容在充放电过程中所需要的时间,它取决于电容器本身的特性和外部电路的参数。在本文中,将详细探讨时间常数对电路的影响,包括对电流、电压、功率
    的头像 发表于 12-20 09:52 3051次阅读

    使用AD5293的过程中遇到的几个问题求解

    我在使用AD5293的过程中遇到了以下几个问题: 1.AD5293的VDD,VSS,VLOGIC引脚所连接的10uf的电容是有极性还是无极性的? 2.EXT_CAP引脚,在上电时对地电压应该是
    发表于 12-11 08:21

    在使用AD4114过程中遇到的问题,请帮忙解答

    哈罗 在使用AD4114的过程中遇到问题,请帮忙解答。多谢! 1.设置AD4114为Continuous Conversion Mode和Continuous Read Mode时,连续读回来通道数
    发表于 12-04 08:06