opengl

OpenGL ES 框架详细解析(十一) —— 并发和OpenG

2017-10-02  本文已影响468人  刀客传奇

版本记录

版本号 时间
V1.0 2017.10.02

前言

OpenGL ES是一个强大的图形库,是跨平台的图形API,属于OpenGL的一个简化版本。iOS系统可以利用OpenGL ES将图像数据直接送入到GPU进行渲染,这样避免了从CPU进行计算再送到显卡渲染带来的性能的高消耗,能带来来更好的视频效果和用户体验。接下来几篇就介绍下iOS 系统的 OpenGL ES框架。感兴趣的可以看上面几篇。
1. OpenGL ES 框架详细解析(一) —— 基本概览
2. OpenGL ES 框架详细解析(二) —— 关于OpenGL ES
3. OpenGL ES 框架详细解析(三) —— 构建用于iOS的OpenGL ES应用程序的清单
4. OpenGL ES 框架详细解析(四) —— 配置OpenGL ES的上下文
5. OpenGL ES 框架详细解析(五) —— 使用OpenGL ES和GLKit进行绘制
6. OpenGL ES 框架详细解析(六) —— 绘制到其他渲染目的地
7. OpenGL ES 框架详细解析(七) —— 多任务,高分辨率和其他iOS功能
8. OpenGL ES 框架详细解析(八) —— OpenGL ES 设计指南
9. OpenGL ES 框架详细解析(九) —— 调整您的OpenGL ES应用程序
10. OpenGL ES 框架详细解析(十) —— 使用顶点数据的最佳做法

Concurrency and OpenGL ES - 并发和OpenGL ES

在计算中,并发通常是指同时在多个处理器上执行任务。 通过并行执行工作,任务尽快完成,应用程序对用户的响应更快。 精心设计的OpenGL ES应用程序在GPU上的应用程序处理和GPU上的OpenGL ES处理之间已经展现出一种特定的并发形式的并发性。OpenGL ES Design Guidelines 中引入的许多技术专门用于创建展示出优秀CPU-GPU并行性的OpenGL应用程序。 设计并发应用程序意味着将工作分解为子任务,并确定哪些任务可以并行安全运行,哪些任务必须顺序执行,即哪些任务依赖于其他任务使用的资源或从这些任务返回的结果。

iOS中的每个进程都由一个或多个线程组成。 线程是运行流程的执行流。 苹果提供传统线程和一个名为Grand Central Dispatch(GCD)的功能。 使用Grand Central Dispatch,您可以将任务分解为子任务,而无需手动管理线程。 GCD根据设备上可用的核心数量分配线程,并自动将任务调度到这些线程。

在更高层次上,Cocoa Touch提供NSOperation和NSOperationQueue,以提供用于创建和调度工作单元的Objective-C抽象。

本章不详细介绍这些技术。 在考虑如何向OpenGL ES应用程序添加并发之前,请参阅 Concurrency Programming Guide。 如果您打算手动管理线程,请参阅Threading Programming Guide。 无论使用哪种技术,在多线程系统上调用OpenGL ES时还有其他限制。 本章帮助您了解多线程程序如何提高OpenGL ES应用程序的性能,OpenGL ES对多线程应用程序的限制以及可用于在OpenGL ES应用程序中实现并发性的常见设计策略。


Deciding Whether You Can Benefit from Concurrency - 决定是否可以从并发中受益

创建多线程应用程序需要在设计,实施和测试应用程序方面付出巨大的努力。 线程也增加了复杂性和开销。 您的应用程序可能需要复制数据,以便将其传递给工作线程,或者多个线程可能需要同步访问相同的资源。 在尝试在OpenGL ES应用程序中实现并发之前,请使用OpenGL ES Design Guidelines中描述的技术在单线程环境中优化OpenGL ES代码。 重点是首先实现优秀的CPU-GPU并行性,然后评估并发编程是否可以提供额外的性能。

一个好的候选结果具有以下特征之一或两者:

如果您的应用程序被阻止等待GPU,并且没有工作,它可以与其OpenGL ES绘图并行执行,那么并不是并发好的选择。 如果CPU和GPU都处于空闲状态,那么您的OpenGL ES需要很简单,无需进一步调整。


OpenGL ES Restricts Each Context to a Single Thread - OpenGL ES将每个上下文限制为单个线程

iOS中的每个线程都有一个当前的OpenGL ES呈现上下文。 每当您的应用程序调用OpenGL ES函数时,OpenGL ES会隐式查找与当前线程相关联的上下文,并修改与该上下文关联的状态或对象。

OpenGL ES不可重入 如果同时从多个线程修改相同的上下文,则结果是不可预测的。 您的应用程式可能会崩溃,否则可能会造成错误。 如果由于某种原因,您决定设置多个线程来定位相同的上下文,那么您必须通过将所有OpenGL ES调用的互斥体放置在上下文中来同步线程。 阻塞的OpenGL ES命令(如glFinish)不同步线程。

GCD和NSOperationQueue对象可以在他们选择的线程上执行你的任务。 他们可以专门为该任务创建一个线程,或者它们可以重用现有的线程。 但是无论如何,您不能保证哪个线程执行任务。 对于OpenGL ES应用程序,这意味着:


Strategies for Implementing Concurrency in OpenGL ES Apps - 在OpenGL ES应用程序中实现并发策略

并发OpenGL ES应用程序应该专注于CPU并行性,以便OpenGL ES可以为GPU提供更多的工作。 以下是在OpenGL ES应用程序中实现并发性的几个策略:


Multithreaded OpenGL ES - 多线程OpenGL ES

每当您的应用程序调用OpenGL ES函数时,OpenGL ES将处理参数,使其以硬件所理解的格式。 处理这些命令所需的时间取决于输入是否已经是硬件友好的格式,但在为硬件准备命令时总是有开销。

如果您的应用程序花费大量时间在OpenGL ES中执行计算,并且您已经采取措施选择理想的数据格式,则通过为OpenGL ES上下文启用多线程,您的应用程序可能会获得额外的好处。 多线程OpenGL ES上下文自动创建一个工作线程,并将其一些计算转移到该线程。 在多核设备上,启用多线程功能可以使CPU上执行的内部OpenGL ES计算与应用程序并行运行,从而提高性能。 同步函数继续阻止调用线程。

要启用OpenGL ES多线程,请将EAGLContext对象的multiThreaded属性的值设置为YES。

注意:启用或禁用多线程执行会导致OpenGL ES刷新以前的命令,并导致设置附加线程的开销。 在初始化函数中而不是在渲染循环中启用或禁用多线程。

启用多线程意味着OpenGL ES必须复制参数以将其传输到工作线程。 由于这种开销,始终使用和不使用多线程来测试应用程序,以确定是否提供了显着的性能改进。 您可以通过在多线程应用程序中实现自己的x OpenGL ES使用策略来最小化此开销,如本章的其余部分所述。


Perform OpenGL ES Computations in a Worker Task - 在工作任务中执行OpenGL ES计算

某些应用程序在将数据传递到OpenGL ES之前对其数据执行大量计算。 例如,应用程序可能会创建新的几何体或对现有的几何体进行动画。 在可能的情况下,这样的计算应该在OpenGL ES中执行。 这充分利用GPU内部更大的并行性,并减少了在应用程序和OpenGL ES之间复制结果的开销。

Figure 6-6 中描述的方法在更新OpenGL ES对象和执行使用这些对象的渲染命令之间进行交替。 OpenGL ES在GPU上呈现与应用程序在CPU上运行的更新的并行。 如果在CPU上执行的计算所花费的时间比GPU上的处理时间更长,那么GPU花费更多的空闲时间。 在这种情况下,您可以在具有多个CPU的系统上利用并行性。 将OpenGL ES渲染代码分解为单独的计算和处理任务,并且并行运行它们。 一个任务会生成第二个要使用的数据并将其提交给OpenGL。

为获得最佳性能,请避免在任务之间复制数据 不是在一个任务中计算数据并将其复制到另一个任务中的顶点缓冲对象中,而是将顶点缓冲区对象映射到设置代码中,并将指针直接传递给工作任务。

如果您可以进一步将修改任务分解为子任务,则可能会看到更好的收益。 例如,假设两个或多个顶点缓冲区对象,每个顶点缓冲区对象在提交绘图命令之前都需要更新。 每个都可以独立于其他的重新计算。 在这种情况下,对每个缓冲区的修改成为一个操作,使用NSOperationQueue对象来管理工作:


Use Multiple OpenGL ES Contexts - 使用多个OpenGL ES上下文

使用多个上下文的一个常见方法是具有更新OpenGL ES对象的一个上下文,而另一个上下文消耗这些资源,每个上下文在单独的线程上运行。 因为每个上下文在一个单独的线程上运行,所以它的动作很少被其他上下文阻止。 要实现这一点,您的应用程序将创建两个上下文和两个线程; 每个线程控制一个上下文。 此外,您的应用程序要在第二个线程上更新的任何OpenGL ES对象必须是双缓冲的; 消耗的线程可能不会访问OpenGL ES对象,而另一个线程正在修改它。 An EAGL Sharegroup Manages OpenGL ES Objects for the Context中详细描述了上下文之间的更改同步过程。

GLKTextureLoader类实现了这种策略来提供纹理数据的异步加载。 (请参阅Use the GLKit Framework to Load Texture Data


Guidelines for Threading OpenGL ES Apps - 线程OpenGL ES应用指南

遵循以下准则,以确保在使用OpenGL ES的应用程序中成功执行线程:

后记

未完,待续~~~

上一篇 下一篇

猜你喜欢

热点阅读