Параллелизм и OpenGL ES

В вычислениях параллелизм обычно относится к выполняющимся задачам больше чем на одном процессоре одновременно. Путем выполнения работы параллельно, задачи, завершенные раньше, и приложения, становятся более быстро реагирующими пользователю. Хорошо разработанный OpenGL приложение ES уже показывает определенную форму параллелизма — параллелизм между обработкой приложения на CPU и OpenGL обработка ES на GPU. Много методов представили в OpenGL, Руководство по проектированию ES нацелено в частности на создание приложений OpenGL, показывающих большой параллелизм CPU-GPU. Разработка параллельного приложения означает анализировать работу в подзадачи и идентифицировать, какие задачи могут безопасно работать параллельно и какие задачи должны быть выполнены последовательно — т.е. какие задачи зависят или от ресурсов, используемых другими задачами или от результатов, возвращенных из тех задач.

Каждый процесс в iOS состоит из одного или более потоков. Поток является потоком выполнения, выполняющего код для процесса. Apple предлагает и традиционные потоки и функцию под названием Grand Central Dispatch (GCD). Используя Центральную Отгрузку, можно анализировать задачу в подзадачи, вручную не управляя потоками. GCD выделяет потоки на основе числа ядер, доступных на устройстве, и автоматически планирует задачи к тем потокам.

В более высоком уровне, Сенсорных предложениях Какао NSOperation и NSOperationQueue обеспечить абстракцию Objective C для создания и планирования единиц работы.

Эта глава не описывает эти технологии подробно. Перед рассмотрением, как добавить параллелизм к OpenGL приложение ES, консультируйтесь с Руководством по программированию Параллелизма. Если Вы планируете управлять потоками вручную, также см. Руководство по программированию Поточной обработки. Независимо от которого метода Вы используете, существуют дополнительные ограничения при вызове OpenGL ES в многопоточных системах. Эта глава помогает Вам понять, когда многопоточность улучшает Ваш OpenGL производительность приложения ES, ограничения OpenGL места ES на многопоточном приложении и общих стратегиях проектирования, Вы могли бы использовать для реализации параллелизма в OpenGL приложение ES.

Решение, можно ли получить преимущества от параллелизма

Создание многопоточного приложения требует значительного усилия в проекте, реализации и тестировании Вашего приложения. Потоки также добавляют сложность и наверху. Ваше приложение, возможно, должно скопировать данные так, чтобы это могло быть вручено рабочему потоку, или многократные потоки, возможно, должны синхронизировать доступ к тем же ресурсам. Прежде чем Вы попытаетесь реализовать параллелизм в OpenGL приложение ES, оптимизируйте свой OpenGL код ES в однопоточной среде с помощью методов, описанных в OpenGL Руководство по проектированию ES. Внимание на достижение большого параллелизма CPU-GPU сначала и затем оценивает, может ли параллельное программирование обеспечить дополнительную производительность.

Хороший кандидат имеет или или обе из следующих характеристик:

Если Ваше приложение блокируется, ожидая GPU и не имеет никакой работы, оно может выполнить параллельно с ее OpenGL получение ES, то это не хороший кандидат на параллелизм. Если CPU и GPU оба неактивны, то Ваш OpenGL , потребности ES, вероятно, достаточно просты, что не необходима никакая дальнейшая настройка.

OpenGL ES ограничивает каждый контекст единственным потоком

Каждый поток в iOS имеет единственный текущий OpenGL контекст рендеринга ES. Каждый раз, когда Ваше приложение вызывает OpenGL функция ES, OpenGL ES неявно ищет контекст, связанный с текущим потоком, и изменяет состояние или объекты, связанные с тем контекстом.

OpenGL ES не повторно используем. При изменении того же контекста от многократных потоков одновременно результаты непредсказуемы. Ваше приложение могло бы отказать, или оно могло бы представить неправильно. Если по некоторым причинам Вы решаете установить больше чем один поток для предназначения для того же контекста, то необходимо синхронизировать потоки путем размещения взаимного исключения вокруг всего OpenGL вызовы ES к контексту. Команды OpenGL ES, блокирующие — такой как glFinish— не синхронизируйте потоки.

GCD и NSOperationQueue объекты могут выполнить Ваши задачи на потоке их выбора. Они могут создать поток в частности для той задачи, или они могут снова использовать существующий поток. Но в любом случае, Вы не можете гарантировать, какой поток выполняет задачу. Для OpenGL приложение ES, означающее:

Стратегии реализации параллелизма в OpenGL приложения ES

Параллельное приложение ES OpenGL должно фокусироваться на параллелизме CPU так, чтобы OpenGL ES мог обеспечить больше работы для GPU. Вот несколько стратегий реализации параллелизма в OpenGL приложение ES:

Многопоточный OpenGL ES

Каждый раз, когда Ваше приложение вызывает OpenGL функция ES, OpenGL , ES обрабатывает параметры для помещения их в формат, который понимают аппаратные средства. Время, требуемое обработать эти команды, варьируется в зависимости от того, являются ли вводы уже в благоприятном для аппаратных средств формате, но там является всегда служебным в подготовке команд для аппаратных средств.

Если Ваше приложение проводит много времени, выполняя вычисления в OpenGL ES, и Вы уже предприняли шаги для выбора идеальных форматов данных, приложение могло бы получить дополнительную выгоду путем включения многопоточности для OpenGL контекст ES. Многопоточный OpenGL контекст ES автоматически создает рабочий поток и передает некоторые его вычисления к тому потоку. На многожильном устройстве, включая многопоточность позволяет внутреннему OpenGL вычисления ES, выполняемые на CPU для действия параллельно с приложением, улучшая производительность. Синхронизирующиеся функции продолжают блокировать вызывающий поток.

Чтобы включить OpenGL многопоточность ES, установите значение multiThreaded свойство Вашего EAGLContext объект к YES.

Включение многопоточности означает OpenGL , ES должен скопировать параметры для передачи их к рабочему потоку. Из-за этих издержек всегда тестируйте свое приложение с, и без многопоточности включил, чтобы определить, обеспечивает ли это улучшение исполнения всех условий. Можно минимизировать эти издержки путем реализации собственной стратегии x OpenGL использование ES в многопоточном приложении, как описано в остатке от этой главы.

Выполните OpenGL вычисления ES в задаче работника

Некоторое приложение выполняет много вычислений на их данных перед передачей данных к OpenGL ES. Например, приложение могло бы создать новую геометрию или анимировать существующую геометрию. Где возможно, такие вычисления должны быть выполнены в OpenGL ES. Это использует в своих интересах больший параллелизм, доступный в GPU, и сокращает издержки копирования результатов между Вашим приложением и OpenGL ES.

Подход описал в альтернативах рисунка 6-6 между обновлением OpenGL объекты ES и выполнением команд рендеринга, использующих те объекты. OpenGL ES представляет на GPU параллельно с обновлениями Вашего приложения, работающими на CPU. Если вычисления, выполняемые на CPU, занимают больше времени обработки, чем те на GPU, то GPU проводит больше неактивного времени. В этой ситуации можно быть в состоянии использовать в своих интересах параллелизм в системах с многократным CPUs. Разделите свой OpenGL код рендеринга ES на отдельное вычисление и обработку задач, и выполните их параллельно. Одна задача производит данные, использующиеся вторым и представленным к OpenGL.

Для лучшей производительности избегите копировать данные между задачами. Вместо того, чтобы вычислять данные в одной задаче и копировать его в буферный объект вершины в другом, отобразитесь, буферный объект вершины в установке кодируют и вручают указатель непосредственно на задачу работника.

Если можно далее анализировать задачу модификаций в подзадачи, можно видеть лучшие преимущества. Например, примите два или больше буферных объекта вершины, каждый из которых должен быть обновлен прежде, чем представить команды рисования. Каждый может быть повторно вычислен независимо от других. В этом сценарии модификации к каждому буферу становятся работой, с помощью NSOperationQueue объект управлять работой:

  1. Установите текущий контекст.

  2. Отобразите первый буфер.

  3. Создайте NSOperation возразите, чья задача состоит в том, чтобы заполнить тот буфер.

  4. Очередь, что работа на очереди работы.

  5. Выполните шаги 2 - 4 для других буферов.

  6. Вызвать waitUntilAllOperationsAreFinished на очереди работы.

  7. Не отобразите буферы.

  8. Выполните команды рендеринга.

Используйте многократный OpenGL контексты ES

Один общий подход для использования многократных контекстов должен иметь один контекст, обновляющий OpenGL объекты ES, в то время как другой использует те ресурсы, с каждым контекстом, работающим на отдельном потоке. Поскольку каждый контекст работает на отдельном потоке, его действия редко блокируются другим контекстом. Для реализации этого приложение создало бы два контекста и два потока; каждый поток управляет одним контекстом. Далее, любой OpenGL , ES возражает Вашему приложению, намеревается обновить на втором потоке, должен быть дважды буферизован; поток потребления может не получить доступ к OpenGL объект ES, в то время как другой поток изменяет его. Процесс синхронизации изменений между контекстами описан подробно в EAGL Sharegroup, Управляет OpenGL Объекты ES для Контекста.

GLKTextureLoader класс реализует эту стратегию обеспечить асинхронную загрузку данных текстуры. (См. Использование Платформа GLKit для Загрузки Данных Текстуры.)

Инструкции для поточной обработки OpenGL приложения ES

Следуйте этим инструкциям для обеспечения успешной поточной обработки в приложении, использующем OpenGL ES: