В своей нынешней форме 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