Параллельное программирование в OpenCL против Grand Central Dispatch

С появлением OpenCL 2.0 OpenCL, похоже, обладает многими функциями Grand Central Dispatch (GCD), такими как блоки и очереди в стиле CLang / Apple. Глядя на их соответствующие наборы функций, мне интересно, может ли OpenCL делать все, что может делать GCD / libdispatch, но с добавленной способностью направлять вычисления как на графический процессор, так и на центральный процессор - или если GCD может предложить что-то особенное. из OpenCL.

В частности, мои вопросы:

  1. Что отличает функции параллелизма в GCD и OpenCL?

  2. Если есть смысл использовать их вместе (при условии, что GCD предлагает дополнительные функции), можно ли маршрутизировать блоки C либо в очереди GCD, либо в очереди OpenCL? И если нацелен на ЦП, будет ли причина проходить через OpenCL, а не работать напрямую

  3. Предлагает ли OpenCL 2.0 балансировку нагрузки в стиле GCD, которая может заполнять потоки, охватывающие как CPU, так и GPU?


person Troy Harvey    schedule 01.02.2014    source источник
comment
На ваш третий вопрос: OpenCL 2.0 не предлагает балансировки нагрузки. Распределение нагрузки между графическими процессорами и ядрами ЦП зависит от приложения (или используемой им инфраструктуры), если они хотят использовать всю машину.   -  person Dithermaster    schedule 02.02.2014
comment
Отвечая на ваш первый вопрос, я начну с того, что я знаю о GCD меньше, чем OpenCL, но для меня GCD - это параллелизм на уровне задач, а OpenCL - это, как правило, параллелизм на уровне данных.   -  person Dithermaster    schedule 02.02.2014
comment
Я понимаю, что в идеале вычисления на графическом процессоре управляются данными. Однако, если и OpenCL, и GCD поддерживают Clang Blocks в качестве единицы вычисления, они помещаются в аналогичную структуру кодовых блоков и архитектурную структуру. Поэтому я не уверен, что рассматриваю реализации как уровень задач и уровень данных.   -  person Troy Harvey    schedule 02.02.2014
comment
Блокирует ли OpenCL Clang задачи, поставленные в очередь с помощью GDC, выполняются только на CPU, или они могут выполняться на GPU?   -  person Dithermaster    schedule 02.02.2014
comment
Это, безусловно, одно различие. Блок GCD может выполняться только на ЦП, если вы не запустите OpenCL через очередь GCD.   -  person Troy Harvey    schedule 02.02.2014


Ответы (3)


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

  • clEnqueuNDRangeKernel: используется для постановки ядра в очередь с N-мерным размером рабочей группы. Обычно используется для параллельной обработки данных.
  • clEnqueueTask: используется для постановки ядра в очередь, состоящего из одного рабочего элемента. Этот примитив, используемый для параллельного выполнения задач, по существу эквивалентен clEnqueueNDRangeKernel с глобальным рабочим размером 1. Он был удален из спецификации OpenCL 2.0.
  • clEnqueueNativeKernel ставит в очередь встроенную функцию C / C ++ в устройство (если оно поддерживает собственные ядра), преимущество заключается в том, что вы можете использовать механизм организации очереди (и упорядочивание в очереди), а также напрямую обращаться к данным буфера из контекста OpenCL. В остальном это очень похоже на концепцию потока или задачи.

Таким образом, хотя OpenCL явно берет свое начало в параллельной обработке данных на графических процессорах и по-прежнему наиболее подходит для обработки данных, которые можно каким-то образом принудительно использовать в 1, 2 или трехмерной сетке, также возможна и ориентированная на задачи обработка. Преимущества становятся более очевидными, когда кто-то начинает ориентироваться на гетерогенные системы с несколькими процессорами, графическими процессорами, DSP и ускорителями, поскольку OpenCL может нацеливаться на все эти устройства с помощью одного формализма.

GCD, с другой стороны, предоставляет удобную библиотеку, которая освобождает разработчика от большей части бремени управления и планирования задач, опираясь на концепцию очередей (разных типов и приоритетов). Таким образом, использование GCD может привести к меньшему риску ошибок и более компактному коду в симметричных многопроцессорных системах.

Таким образом, хотя OpenCL и GCD изначально имеют разное происхождение (помимо того факта, что они оба пришли из Apple), они оба используют очереди в своей основе для управления распределением рабочих элементов. У них обоих есть понятие «контекст» для определения доступа к данным.

Начиная с версии OS X 10.7, можно использовать GCD для отправки ядер OpenCL (аналогично блокам) на устройства, поддерживающие OpenCL, что открывает потенциал для объединения преимуществ / сильных сторон как OpenCL, так и GCD.

Вот попытка некоторых ответов / идей относительно w.r.t. ваши конкретные вопросы:

1 - Что отличает функции параллелизма в GCD и OpenCL?

Как указали @Dithermaster и @sharpneli, изначально GCD был ориентирован на ориентированную на задачи (симметричную много-) обработку, в то время как OpenCL изначально предназначался для параллельной обработки данных в гетерогенных архитектурах.

Одно из основных различий между OpenCL и GCD заключается в механизме организации очередей. Например, хотя и OpenCL, и GCD поддерживают синхронное и асинхронное выполнение, GCD имеет три приоритета для глобальных асинхронных очередей. Среда выполнения OpenCL этого не имеет (она выполняет выполнение рабочих элементов вне очереди, но не определено, какие рабочие элементы среда выполнения выполнит в первую очередь).

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

Еще одно отличие заключается в используемой модели согласованности памяти. OpenCL использует упрощенную модель для ядер с глобальной, локальной, частной и постоянной памятью. В НОД этого нет.

С другой стороны, OpenCL имеет векторные типы данных и векторные встроенные функции, позволяющие напрямую задействовать SIMD-потенциал архитектуры, не полагаясь на компилятор. На некоторых архитектурах это выгодно, в то время как другие архитектуры (например, MIC) рекомендуют не векторизовать вручную.

Наконец - хотя это не совсем функция параллелизма - OpenCL имеет функции, которые позволяют читать и записывать типы изображений, что по сути дает вам прямой доступ к памяти текстур. Это часто может использоваться для получения значительного ускорения даже для алгоритмов, не связанных с обработкой изображений.

2 - Если есть смысл использовать их вместе (при условии, что GCD предлагает дополнительные функции), можно ли маршрутизировать блоки C либо в очереди GCD, либо в очереди OpenCL? И если нацелен на ЦП, будет ли причина проходить через OpenCL, а не работать напрямую

Используя вместе GCD и OpenCL, вы можете обращаться к любому устройству, поддерживающему OpenCL. Таким образом, вы можете использовать потенциально неоднородную природу своей платформы, при этом имея возможность извлекать выгоду из механизмов более высокого уровня, которые предоставляет GCD, чтобы упростить многопоточность. Написание всего с помощью OpenCL C API (или даже C ++ API), вероятно, приведет к немного большему количеству кода.

Кроме того, GCD предоставляет такие примитивы, как gcl_get_kernel_block_workgroup_info, которые могут рекомендовать оптимальный размер рабочей группы для вашего ядра.

Однако, насколько я понимаю, невозможно направить произвольные блоки C ни в очереди GCD, ни в очереди OpenCL. Блоки C могут идти только в очереди, не относящиеся к OpenCL. Ядра OpenCL могут быть отправлены (со стороны хоста) только в очереди для устройств, поддерживающих OpenCL. Со стороны устройства (то есть из ядра OpenCL) блок может быть отправлен только на то же устройство.

3 - Предлагает ли OpenCL 2.0 балансировку нагрузки в стиле GCD, которая может заполнять потоки, охватывающие как CPU, так и GPU?

Нет, OpenCL 2.0 на самом деле не определяет, как выполнять балансировку нагрузки ни с точки зрения хоста, ни с устройства.

Однако на стороне хоста можно легко разделить вычисление и запустить его часть, скажем, на ЦП, а другую часть - на одном или нескольких графических процессорах. Один из способов сделать это - поиграть с размерами рабочих групп и смещением рабочих групп и скопировать только минимальные данные, необходимые для каждого устройства. Затем можно использовать механизмы автонастройки, чтобы выяснить, как лучше всего распределять нагрузку между различными используемыми устройствами.

Как только драйверы OpenCL 2.0 станут доступны, новые каналы, динамический параллелизм и общая виртуальная память предоставят больше возможностей для эффективного разделения работы между устройствами. Неясно, станут ли эти функции доступными через GCD и каким образом.

person Erik Duymelinck    schedule 06.02.2014
comment
Спасибо за очень вдумчивый ответ - person Troy Harvey; 12.02.2014
comment
Пожалуйста. Несмотря на то, что мой ответ не является окончательным относительно того, является ли использование OpenCL с GCD хорошим выбором для вас, я надеюсь, что это поможет вам принять решение. - person Erik Duymelinck; 16.02.2014

1) Уже хорошо ответил Dithermaster. OpenCL предназначен для случаев, когда ваша проблема очень хорошо распараллеливается и у вас много данных. GCD предназначен для случаев, когда вам нужно легко создать поток для обработки файлового ввода-вывода или еще чего-то. Вы никогда не сможете вызвать какие-либо системные или другие библиотечные функции из OpenCL.

2) Если ваша проблема легко распараллеливается, стоит использовать OpenCL даже на CPU. В качестве примера реализации Intel OpenCL удается горизонтально распараллелить некоторые ядра, так что одно ядро ​​эффективно запускает 8 потоков одновременно (один поток «выполняется» в одном векторном компоненте регистра SSE).

Вы не можете передать общие блоки C в OpenCL. Просто само ядро ​​и не более того. OpenCL более требователен к тому, что вы можете на нем выполнить. Единственное, что предлагает новомодный Clang IR, - это возможность избежать распространения исходного кода ядра в текстовой форме. Он по-прежнему ограничен только кодом ядра OpenCL.

3) Не автоматически. Существуют некоторые реализации, которые это делают. В прошлом году GDC Intel продемонстрировала автоматическую балансировку нагрузки на своем ЦП (одновременно использовались интегрированный графический процессор и ЦП).

OpenCL2.0 на самом деле не заботится о том, на каком HW он работает, поэтому ответственность за реализацию такой функциональности на своих платформах ложится на производителей HW. Или для непересекающихся платформ это головная боль программиста.

person sharpneli    schedule 04.02.2014

«OpenCL имеет векторные типы данных и векторные встроенные функции, позволяющие напрямую использовать SIMD-потенциал архитектуры, не полагаясь на компилятор» - Эрик Дуймелинк

Apple представила iOS 8 и OS X Yosemite

  • 2D, 3D, 4D Векторная машина и геометрия.
  • Возможности Metal в C, Obj-C и C ++ на процессоре
  • Абстракция над архитектурно-зависимой SIMD, типами и внутренностями.
person dr.no    schedule 27.07.2014