gpt4 book ai didi

multithreading - 为什么 GPUImage 使用信号量和处理队列而不是带有运行循环的线程?

转载 作者:行者123 更新时间:2023-12-03 13:19:13 24 4
gpt4 key购买 nike

据我了解 GPUImage 执行 DAG 遍历并使用
信号量以保护 OpenGL 的使用,同时将其与帧缓冲区纹理缓存一起视为一次性资源。

这里有使用信号量的理由吗?他们不是使情况不必要地复杂化了吗?通过为每个过滤器 DAG 使用单独的线程实现而不是在 runloop 中的单独线程上运行,它们提供了什么好处以及会遇到什么样的问题。
是否有特定的设计考虑因素影响了当前 GPUImage 架构的决定?

最佳答案

在使用 OpenGL(ES) 上下文时,如果您一次从多个线程访问它,就会发生不好的事情。您可以简单地在主线程上执行所有渲染和交互代码,但这会干扰您的 UI 并会在 UI 事件期间停止任何图像或视频处理(例如下拉菜单)。还有significant performance advantages在后台线程上进行 OpenGL(ES) 渲染。

因此,您需要一种在后台线程上执行 OpenGL(ES) 渲染同时仍防止同时访问的方法。手动创建的线程和锁是实现此目的的一种方法,但锁具有显着的性能开销,并且正确管理手动创建的线程会添加大量代码(并且可能会浪费资源)。

一次一个 block 的 Grand Central Dispatch 队列是一种高效且相对简单的方法,可提供对此类共享资源的安全、无锁访问。任何想要在上下文中进行 OpenGL(ES) 渲染的地方,只需将其包装在一个 block 中,以便在上下文的串行调度队列上调度。这使您可以轻松查看这些访问在您的代码中发生的位置,并使您免于维护手动线程、运行循环和锁的性能和代码开销。

我在 my answer here 中讨论了我使用调度信号量的原因,但这是一种有选择地丢弃传入帧以响应负载的方法。

使用这样的串行调度队列,我想确保在任何给定时间我只有一个图像或视频帧通过队列工作。使用单个 GPU,一次渲染多个图像没有任何优势。

但是,如果您的相机以每秒 30-60 帧的速度处理帧,并且您的处理管道有时需要超过 1/30 或 1/60 秒来处理这些图像,您必须使决定。您是丢弃传入的帧,还是将它们排入队列以进行处理?如果是后者,您将继续在队列中构建越来越多的帧,直到耗尽可用的处理和内存资源,并且您还会看到越来越大的处理延迟。

如果串行调度队列中已经处理了一个帧,调度信号量允许我立即丢弃帧,并且以一种高性能和安全的方式这样做。它也只添加了几行代码,几乎都可以在my answer here中找到。 (这在 Swift 3 中更短、更易读)。

我在上面描述的架构已经过全面分析,并且是我为这些需求找到的最佳解决方案。多年来,我一直使用它在较旧的 iOS 硬件上提供 60 FPS 的 OpenGL ES 分子模型渲染、Mac 上的实时机器视觉处理以及 iOS 上的实时视频过滤。考虑到多线程代码可能出错的所有事情,事实证明它非常可靠且易于维护。 GCD 队列和信号量的开销从未接近我的视频渲染的性能瓶颈。

关于multithreading - 为什么 GPUImage 使用信号量和处理队列而不是带有运行循环的线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39977594/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com