как узнать cuda или opencl
Сравнение OpenCL с CUDA, GLSL и OpenMP
На хабре уже рассказали о том, что такое OpenCL и для чего он нужен, но этот стандарт сравнительно новый, поэтому интересно как соотносится производительность программ на нём с другими решениями.
В этом топике приведено сравнение OpenCL с CUDA и шейдерами для GPU, а также с OpenMP для CPU.
Тестирование проводилось на задаче N-тел. Она хорошо ложится на параллельную архитектуру, сложность задачи растёт как O(N 2 ), где N — число тел.
Задача
В качестве тестовой была выбрана задача симуляции эволюции системы частиц.
На скриншотах (они кликабельны) видна задача N точечных зарядов в статическом магнитном поле. По вычислительной сложности она ничем не отличается от классической задачи N тел (разве что картинки не такие красивые).
Во время проведения замеров вывод на экран был отключен, а FPS означает число итераций в секунду (каждая итерация — это следующий шаг в эволюции системы).
Результаты
Код на GLSL и CUDA для этой задачи был уже написан сотрудниками ННГУ.
NVidia Quadro FX5600
Версия драйвера 197.45
CUDA обгоняет OpenCL приблизительно на 13%. При этом, если оценивать теоретически возможную производительность для этой задачи для данной архитектуры, реализация на CUDA достигает её.
(В работе A Performance Comparison of CUDA and OpenCL говорится о том, что производительность ядра OpenCL проигрывает CUDA от 13% до 63% )
Несмотря на то, что тесты проводились на карточке серии Quadro, понятно, что обычный GeForce 8800 GTS или GeForce 250 GTS дадут схожие результаты (все три карточки основаны на чипе G92).
Radeon HD4890
ATI Stream SDK версия 2.01
OpenCL проигрывает шейдерам на карточках от AMD так как вычислительный блоки на них имеют архитектуру VLIW, на которую (после оптимизации) могут хорошо лечь многие шейдерные программы, но компилятор для кода OpenCL (который является частью драйвера) плохо справляется с оптимизацией.
Также этот весьма скромный результат может быть вызван тем, что карточки от AMD не поддерживают локальную память на физическом уровне, а отображают область локальной памяти на глобальную.
Код с использованием OpenMP был скомпилирован при помощи компиляторов от Intel и Microsoft.
Компания Intel не выпустила своих драйверов для запуска кода OpenCL на центральном процессоре, поэтому был использован ATI Stream SDK.
Intel Core2Duo E8200
ATI Stream SDK версия 2.01
Код на OpenMP, скомпилированный при помощи MS VC++ имеет практически идентичную производительность с OpenCL.
Это ещё при том, что Intel не выпустил своего драйвера для интерпретации OpenCL, и используется драйвер от AMD.
Компилятор от Intel поступил не совсем «честно» он полностью развернул основной цикл программы, повторив его где-то 8k раз (число частиц было задано константой в коде) и получив семикратный прирост производительности также благодаря использованию SSE инструкций. Но победителей, конечно, не судят.
Что характерно, на моём стареньком AMD Athlon 3800+ код тоже запустился, но таких выдающихся результатов, как на Intel, конечно, ждать не приходится.
Заключение
Введение в OpenCL
Компилятор
Модель памяти устройства
Прежде чем описывать сам язык я дам краткое описание физической модели устройства с которой он взаимодействует. Исполнение команд языка идёт на объектах, называемых «work-item». Каждый «work-item» не зависим от другого и может исполнять код параллельно с остальными. Если же процесс из одного work-item хочет получить данные, используемые или уже обработанные любым другим work-item он может это сделать через общую память. Общая память весьма медленная, зато имеет большой объём. Чтобы ускорить вычисления имеется локальная память. Если вы знакомы с CUDA, то там она называется «разделяемая память». Она значительно быстрее общей, но не любой процесс может получить к ней доступ. К локальной памяти могут обращаться только work-item одной группы. Эти группы называются «Compute Unit» или «Workgroup» (первое название относится к физическому разбиению на уровне железа, а второе к логическому на уровне программы). В зависимости от устройства в каждой из этих групп различное количество work-item (например 240 для NVIDIA GT200 или 256 для Radeon 5700 Series). Количество этих юнитов ограниченно достаточно маленьким числом (30 для NVIDIA GT200 или 9-10 для Radeon 5700 Series). Так же существует сверхбыстрая «private memory» к которой work-item может обращаться единолично.
Драйвера OpenCL устройств автоматизируют старт и работу work-item и workgroup. Например если нам нужно выполнить миллион процессов, а у нас в распоряжении всего тысяча work-item, то драйвера будут автоматически запускать каждый процесс со следующей задачей после его завершения. Понимание физического уровня требуется только для того, чтобы иметь представление о возможностях взаимодействия между процессами и доступа процессов в память.
Базовые особенности
Объявление процедур
В первую очередь в глаза бросается загадочный «__kernel «. Этой директивой должна быть помечена любая процедура, которую мы хотим вызвать извне. Если процедура не нужна при работе извне, её можно не отмечать.
Типы памяти
Тип данных «__global » обозначает память, которая выделяется из глобального адресного пространства работающего устройства. Она достаточна медленная, зато вместительная. Для современных видеокарт измеряется гигобайтами. Если вы работаете на процессоре — под global подразумевается оперативная память.
Кроме global есть «__local «. К ней может обращаться только рабочая группа(workgroup). На каждую такую группу выделяется примерно 8 килобайт.
Так же быстрой памятью является «__privat «. Это память к которой имеет доступ только отдельный поток (work-item). Всего на поток выделяется 32 регистра этой памяти.
Остальные типы памяти, которые можно объявлять при создании ядра основаны на типе «__global «. Во-первых, это «__constant «, который может использоваться только для чтения. Во-вторых, это «__read_only», «__write_only» и «__read_write» — структуры, использование которых разрешено только для изображений.
Идентификаторы процессов
Оптимизация расчётов
Разработчики OpenCL и видеокарт понимали, что основная цель их детища — ускорить сложные расчёты. Для этого в язык был добавлен ряд специализированных особенностей, позволяющих при их использовании получить прирост в скорости на математических задачах.
Встроенные вектора
Простые функции
Следующей особенностью OpenCl является встроенная библиотека функций. Кроме стандартного набора math.lib в OpenCl имеются так называемые native функции. Это функции, основаны непосредственно на использовании некоторых функций видеокарт и на загрублённой математике. Не советуется применять их при сверхточных расчётах, но в случае фильтрации изображений разницу невозможно заметить. К таким функциям, например, относятся: «native_sin», «native_cos», «native_powr». Я не буду приводить более подробное объяснение этих функций, их очень много, да и принципы разные. Если они вам понадобятся — смотрите документацию.
Часто встречающиеся функции
Кроме «простых функций» разработчики создали целый ряд называемый common function. Это функции, часто встречающиеся при обработке изображений. Например: mad(a,b,c) = a*b + c, mix(a,b,c) = a + (b-a)*c. Эти функции выполняются быстрее, чем соответствующие им математические действия.
Пример
Вторая процедура (использующая оптимизацию) выполняется в 35 раз быстрее.
Разрешения
#pragma OPENCL EXTENSION extension name : behavior
Синхронизация
Барьеры
В первом примере на команде barrier ожидают все процессы рабочей группы, во втором — все процессы OpenCL устройства.
Стоит отметить особенность этого примера, команды «__local int x[10];» и «__global int x[10];». Они позволяют выделить глобальную переменную в группе процессов и во всех процессах уже во время их исполнения.
Единичные операции
void GetSemaphor(__global int * semaphor) <
int occupied = atom_xchg(semaphor, 1);
while (occupied > 0)
<
occupied = atom_xchg(semaphor, 1);
>
>
Работа с изображениями
Последней вещью, которую я хочу включить в этот guide является работа с изображениями через OpenCL. Создатели попробовали сделать так, чтобы работа с изображениями требовала минимума мозга пользователя. Это очень приятно. Загрузка изображений возможна в типы image2d_t и image3d_t. Первые — это обычные изображения, вторые — трёхмерные. Так же загружаемое изображение должно быть одного из форматов: » __read_only», » __write_only», «__read_write». Чтение и запись данных из изображения возможны только специальными процедурами: значение = read_imageui(изображение, сэмплер, положение), write_imageui(изображение, положение, значение).
На мой взгляд здесь всё понятно кроме понятия «сэмплер». Сэмплер — это штука, которая будет оптимизировать вашу работу с изображением. У него есть три параметра: «normalized coords», «address mode», «filter mode». Первый имеет два значения: «CLK_NORMALIZED_COORDS_TRUE, CLK_NORMALIZED_COORDS_FALSE». В соответствии с названием он должен показывать, нормализованы ли входные координаты или нет. Второй показывает, что делать в случае, если вы пробуете прочитать координаты из-за пределов границ изображения. Возможные варианты: зеркально продолжить изображение(CLK_ADDRESS_MIRRORED_REPEAT), взять ближайшее граничное значение (CLK_ADDRESS_CLAMP_TO_EDGE), взять базовый цвет (CLK_ADDRESS_CLAMP), ничего не делать (пользователь гарантирует что такого не произойдёт CLK_ADDRESS_NONE). Третий показывает, что делать, если на входе не целые координаты. Возможные варианты: приблизить ближайшим значением (CLK_FILTER_NEAREST), линейно проинтерполировать (CLK_FILTER_LINEAR).
Краткий пример. Замыливаем изображение по среднему значению в области:
__kernel void ImageDiff(__read_only image2d_t bmp1, __write_only image2d_t bmpOut)
Вычисляем на видеокартах. Технология OpenCL. Часть 0. Краткая история GPGPU
22 июня автор курса «Разработчик C++» в Яндекс.Практикуме Георгий Осипов провёл вебинар «Вычисляем на видеокартах. Технология OpenCL».
Мы подготовили для вас его текстовую версию, для удобства разбив её на смысловые блоки.
Цикл будет полезен и тем, кто уже знаком с OpenCL: в нём мы поделимся некоторыми хаками и неочевидными наблюдениями из собственного опыта.
CPU — в помойку?
В статье будем рассматривать технологию GPGPU. Разберёмся, что значат все эти буквы. Начнем с последних трёх — GPU. Все знают аббревиатуру CPU — Central Processor Unit, или центральный процессор. А GPU — Graphic Processor Unit. Это графический процессор. Он предназначен для решения графических задач.
Но перед GPU есть ещё буквы GP. Они расшифровываются как General-Purpose. В аббревиатуре опускают словосочетание Computing on. Если собрать всё вместе, получится General-Purpose Computing on Graphic Processor Unit, что по-русски — вычисления общего назначения на графическом процессоре.
То есть процессор графический, но мы почему-то хотим вычислять на нём что-то, что вообще к графике никакого отношения не имеет. Например, прогноз погоды, майнинг биткоинов. Моя задача в ближайшее время — объяснить, зачем нужно на процессоре для графики обучать, например, нейросети.
Самое распространённое место, где можно обнаружить GPU, — ваша родная видеокарта. Всем известно, что если вставить в неё штекер монитора, появится картинка. На самом деле видеокарта — это не только гнездо для монитора, но и полноценное вычислительное устройство.
Давайте немного отвлечёмся от видеокарты и вернёмся в 2000 год, когда процессоры CPU набирали всё больше и больше мегагерц. Компания Intel тогда прогнозировала, что к 2010 году тактовая частота одного ядра процессора достигнет 10 гигагерц. Сейчас мы знаем, что эти ожидания не сбылись.
По графику видно: рост действительно был очень хороший, но где-то в районе 2004–2005 года он резко остановился. И дальше процессоры стали даже немножко терять в мощности. Развитие центральных процессоров в итоге пошло за счёт увеличения количества ядер. Сейчас в мощных компьютерах у CPU может быть 16 ядер. Но тактовая частота ядра за последние 10 лет не росла.
Если посмотреть на другой график, где сравниваются CPU и GPU, можно увидеть, что процессоры в видеокартах эту тенденцию перехватили. Графический процессор продолжил наращивать мощность и во многом опередил центральные процессоры по производительности. Удивительный факт — процессор, который находится в видеокарте, выполняет гораздо больше операций с плавающей точкой в секунду, чем главный, центральный процессор.
Источник. По вертикали GFLOPS, т. е. миллиарды арифметических операций с плавающей точкой в секунду
Остаётся вопрос: в чём GPU уступают CPU? Может, дело не в процессоре, а в памяти? Для сравнения возьмём современную оперативную память DDR4 и графическую память GDDR5. Но и тут оказывается, что графический контроллер во много раз превосходит обычный CPU: доступ к графической памяти у GPU гораздо быстрее — 400 Гб/сек против 35 Гб/сек.
И ещё сравним какой-нибудь современный процессор и не очень современную видеокарту. Например, GeForce GTX 1080 Ti, которую сейчас можно купить только на Авито, и довольно современный процессор Core i9 с хорошей памятью.
Получается, видеокарта обгоняет процессор… И если Core i9 может сделать 460 миллиардов арифметических операций с плавающей точкой в секунду, то GTX1080Ti уже 11 триллионов. В общем, GTX намного превосходит Core i9 и по производительности, и по скорости доступа к памяти.
Когда я увидел это сравнение, у меня возник вопрос: а может, этот медленный CPU вообще не нужен? Что если выбросить его, оставить только GPU и все задачи решать на графическом адаптере? Ответ такой: GPU, конечно, очень классный, но годится не для любых задач. Если избавиться от CPU, всё будет немножечко лагать. Так делать не надо.
GPU хорош для массового параллелизма, когда одновременно выполняется огромное количество очень похожих вычислений. Но тут есть такие весы. На одной чаше latency — задержка, на другой флопсы — количество операций. Например, если операция длится секунду, это очень долго. Но если вы одновременно можете выполнить 100 миллиардов таких операций, у вас получились 100 миллиардов операций в секунду. Для CPU это довольно плохо, потому что нам нужно, чтобы всё работало последовательно. А для GPU — нормально. Главное — не задержка, а результат. Числа в этом примере, конечно, сильно утрированы, реальный параллелизм GPU — порядка нескольких тысяч.
Массовый параллелизм
Хороший пример задачи массового параллелизма — Ray Tracing, или трассировка лучей. В экране много пикселей, и из каждого пикселя выпускается луч, чтобы получить качественный рендер всей сцены. Эти лучи можно обрабатывать параллельно, независимо вычисляя цвет каждого пикселя экрана. Значит, это задача массового параллелизма. Существует прекрасный сайт, на котором вы можете, не отходя от браузера, попрактиковаться в написании трассировщика лучей, работающего на GPU. Там можно найти немало любопытных примеров.
Майнинг биткоинов. Чтобы намайнить биткоины, нужно вычислить много хешей и найти среди них обладающий определёнными свойствами. И у этой задачи, к сожалению, или к счастью, нет существенно лучшего решения, чем просто вычислять хеши, пока вам наконец не повезёт. Хеши считаются независимо, и это можно делать параллельно. Значит, это задача массового параллелизма. Майнинг прекрасно ложится на видеокарту.
Обучение нейросетей. Основная затратная операция, которая используется в Deep Learning, — свёртка изображений. Это вычислительно сложная операция, ведь для подсчёта одного значения свёртки с ядром 5⨯5 нужно произвести 25 умножений и 24 сложения. Радует одно: все значения можно считать независимо. А значит, это задача массового параллелизма.
Многие учёные используют GPU в своих задачах, потому что научных данных часто бывает очень много, они долго обрабатываются, и графический процессор тут иногда применим. Если вы один из таких учёных, то спешу вас обрадовать: на самом деле в программировании под GPU нет ничего сложного, и в этом цикле статей мы напишем полноценную программу под него.
Тем, кто серьёзно заинтересовался вычислениями на видеокартах, я рекомендую прекрасные лекции Николая Полярного. Там он разбирает эту тему гораздо подробнее, чем я. С его разрешения я взял вот эту картинку, которая хорошо показывает соотношение CPU и GPU.
Здесь приведены усреднённые данные. На блок L1/Local memory пока не смотрите, разберём его чуть позже. Видно, что CPU может иметь производительность в 20 гигафлопс, а GPU — в 5000 гигафлопс. Канал памяти у GPU гораздо выше. Но есть одно узкое местечко — шина PCI-E. Она соединяет RAM и GRAM и пропускает всего 8 Гб. Глядя на эту картинку, попробуйте ответить на вопрос: есть ли смысл решать все задачи массового параллелизма с помощью графического процессора?
Предположим, задача — сложить два массива чисел по 10 миллиардов: первое складываем с первым, второе со вторым и так далее. Нужно получить сумму, третий набор чисел. Поручать ли такую задачу графическому процессору?
Понятно, что это задача массового параллелизма. Но есть один момент. Для того, чтобы эти числа сложить на GPU, их нужно сначала передать на GRAM по узенькому мостику в 8 Гб/сек. Видеокарта посчитает всё очень быстро, это факт. Но потом вам нужно будет эти данные передавать по мостику обратно. И окажется, что гораздо быстрее просто передать по большему каналу в CPU, и он своими жалкими 20 гигафлопсами сложит числа быстрее, чем если бы они ехали по шине в GPU.
Правда, уже есть некоторые решения этой проблемы. Технология NVLink позволяет ускорить передачу данных в видеопамять с 8 до 40 Гб/сек. Более того, у некоторых дешёвых видеокарт нет видеопамяти, и они могут обращаться напрямую к RAM. Но мы не будем затрагивать этот момент.
Краткая история GPGPU
Технология GPGPU появилась не сразу. До этого графический адаптер использовался исключительно по назначению. Но когда люди увидели, какие у GPU мощности, им захотелось использовать эти мощности для своих неграфических задач. Тогда приходилось выкручиваться и как-то маскировать свою неграфическую задачу под графическую. Видеокарта думала, что рисует треугольники, а на самом деле вычисляла и обрабатывала научные данные. К счастью, разработчики видеокарт увидели эту проблему и пошли навстречу. Так появилась OpenCL и другие технологии, о которых я немного расскажу.
До появления OpenCL возникла очень популярная технология, отличающаяся только одной буквой, — OpenGL. Она решала графические задачи, нужные в первую очередь для видеоигр.
Я выделил три этапа развития OpenGL:
Первая версия появилась в 1994 году. В 2001 году произошло важное событие: стало возможным написание шейдеров на языке GLSL. Если раньше вы могли просить нарисовать треугольники с конкретными параметрами и текстурами, то в 2001 году появилась возможность запускать свой код на видеокарте, то есть самому писать обработчик, который будет вычислять цвет пикселя и его положение. В 2008 году разработка OpenGL перешла консорциуму Khronos Group. Запомните это название, оно вам ещё встретится.
Идея, лежащая в основе OpenGL, состоит в том, что любую геометрическую фигуру можно приблизить треугольниками. Отрисовывать их OpenGL может с огромной скоростью. Если видеоигра, использующая OpenGL, содержит шейдеры, то они будут скомпилированы в момент запуска игры на компьютере пользователя. Код шейдеров будет исполнен непосредственно процессором видеокарты — это и есть та лазейка, которую использовали ранее для неграфических вычислений с OpenGL.
Назвать OpenGL современной технологией уже нельзя. Ей на смену пришли Vulkan и Metal. И если OpenGL направлена на графику, то Vulkan и Metal более универсальны. Останавливаться на них не будем.
Как я уже сказал, если вам нужна графика, то можно либо замаскировать задачу под графическую, либо использовать специальную технологию, предназначенную для решения неграфических задач на видеокартах. Для этого есть две основных технологии — OpenCL, виновница сегодняшнего торжества, и её конкурент CUDA.
Главное их отличие друг от друга — в том, что CUDA поддерживает только видеокарты NVIDIA. Никакие другие адаптеры запустить CUDA-код не смогут. С другой стороны, в этом есть плюсы. Вы знаете, на каких видеокартах код будет запускаться, поэтому под них можно его хорошо отладить и предварительно скомпилировать.
У карт NVIDIA есть несколько версий API, и вы решаете, под какую версию API из доступных скомпилировать код CUDA. Если выбрать какую-то одну, код на более старых видеокартах не пойдёт, а на более новых не будет супероптимальным. Поэтому лучше компилировать сразу под несколько версий.
В OpenCL возможности предкомпиляции нет, потому что вы не знаете, на каком устройстве код будет запускаться. Исключения, конечно, бывают. Например, вы заключили договор с клиентом, и он говорит, что программа будет запускаться на такой-то видеокарте. Тогда вы можете скомпилировать под неё и отправлять заказчику только собранный OpenCL-код. Но для конечного пользователя так лучше не делать.
Обе эти технологии ушли или уходят с macOS, на ней остаётся Metal. Но что я хочу сказать: видеокарта одна, и бэкенд, на котором всё будет выполняться, один. А значит, любые технологии похожи между собой.
В следующей части мы разберём основные понятия, которые необходимо знать, чтобы написать программу с использованием OpenCL.
OpenCL. Что это такое и зачем он нужен? (если есть CUDA)
Здравствуй, уважаемое хабра-сообщество.
Многие, наверное, слышали или читали на хабре об OpenCL – новом стандарте для разработки приложений для гетерогенных систем. Именно так, это не стандарт для разработки приложений для GPU, как многие считают, OpenCL изначально задумывался как нечто большее: единый стандарт для написания приложений, которые должны исполняться в системе, где установлены различные по архитектуре процессоры, ускорители и платы расширения.
Предпосылки появления OpenCL
Стоит отметить, что подобные программы создавались и раньше, но именно NVidiaа CUDA обеспечила рост популярности GPGPU за счет облегчения процесса создания GPGPU приложений. Первые GPGPU приложения в качестве ядер (kernel в CUDA и OpenCL) использовали шейдеры, а данные запаковывались в текстуры. Таким образом необходимо было быть хорошо знакомым OpenGL или DirectX. Чуть позже появился язык Brook, который немного упрощал жизнь программиста (на основе этого языка создавалась AMD Stream (в ней используется Brook+) ).
CUDA стала набирать обороты, а между тем (а точнее несколько ранее) в кузнице, расположенной глубоко под землей, у подножия горы Фуджи (Fuji), японскими инженерами был выкован процессор всевластия Cell (родился он в сотрудничестве IBM, Sony и Toshiba). В настоящее время Cell используется во всех суперкомпьютерах, поставляемых IBM, на его основе постоены самые производительные в мире суперкомпьютеры (по данным top500). Чуть менее года назад компания Toshiba объявила о выпуске платы расширения SpursEngine для PC для ускорения декодирования видео и прочих ресурсоемких операций, используя вычислительные блоки (SPE), разработанные для Cell. В википедии есть статья, в кратце описывающая SpursEngine и его отличия от Cell.
Примерно в то же время (около года назад) оживилась и S3 Graphics (на самом деле VIA), представив на суд общественности свой новый графический адаптер S3 Graphics Chrome 500. По заявлениям самой компании этот адаптер так же умеет ускорять всяческие вычисления. В комплекте с ним поставляется программный продукт (графический редактор), который использует все прелести такого ускорения. Описание технологии на сайте производителя.
Итак, что мы имеем: машина, на которой проводятся вычисления может содержать процессоры x86, x86-64, Itanium, SpursEngine (Cell), NVidia GPU, AMD GPU, VIA (S3 Graphics) GPU. Для каждого из этих типов процессов существует свой SDK (ну кроме разве что VIA), свой язык программирования и программная модель. То есть если Вы захотите чтобы ваш движок рендеринга или программа расчета нагрузок на крыло боинга 787 работала на простой рабочей станции, суперкомпьютере BlueGene, или компьютере оборудованном двумя ускорителями NVidia Tesla – Вам будет необходимо переписывать достаточно большую часть программы, так как каждая из платформ в силу своей архитектуры имеет набор жестких ограничений.
Так как программисты – народ ленивый, и не хотят писать одно и то же для 5 различных платформ с учетом всех особенностей и учиться использовать разные программные средства и модели, а заказчики – народ жадный и не хотят платить за программу для каждой платформы как за отдельный продукт и оплачивать курсы обучения для программистов, было решено создать некий единый стандарт для программ, исполняющихся в гетерогенной среде. Это означает, что программа, вообще говоря, должна быть способна исполняться на компьютере, в котором установлены одновременно GPU NVidia и AMD, Toshiba SpursEngine итд.
Решение проблемы
Для разработки открытого стандарта решили привлечь людей, у которых уже есть опыт (весьма успешный) в разработке подобного стандарта: Khronos Group, на чьей совести уже OpenGL и OpenML и еще много всего. OpenCL является торговой маркой Apple Inc., как сказано на сайте Khronos Group: «OpenCL is a trademark of Apple Inc., and is used under license by Khronos. The OpenCL logo and guidelines for its usage in association with Conformant products can be found here:
http://developer.apple.com/softwarelicensing/agreements/opencl.html». В разработке (и финансировании, конечно же), кроме Apple, участвовали такие воротилы IT как AMD, IBM, Activision Blizzard, Intel, NVidia итд. (полный список тут).
Компания NVidia особо не афишировала свое участие в проекте, и быстрыми темпами наращивала функциональность и производительность CUDA. Тем временем несколько ведущих инженеров NVidia участвовали в создании OpenCL. Вероятно, именно участие NVidia в большой мере определило синтаксическую и идеологическую схожесть OpenCL и CUDA. Впрочем программисты от этого только выиграли – проще будет перейти от CUDA к OpenCL при необходимости.
Первая версия стандарта была опубликована в конце 2008 года и с тех пор уже успела претерпеть несколько ревизий.
Почти сразу после того как стандарт был опубликован, компания NVidia заявила что поддержка OpenCL не составит никакой сложности для нее и в скором времени будет реализована в рамках GPU Computing SDK поверх CUDA Driver API. Ничего подобного от главного конкурента NVidia – AMD слышно не было.
Драйвер для OpenCL был выпущен NVidia и прошел проверку на совместимость со стандартом, но все еще доступен только для ограниченного круга людей – зарегистрированных разработчиков (заявку на регистрацию подать может любой желающий, в моем случае рассмотрение заняло 2 недели, после чего по почте пришло приглашение). Ограничения доступа к SDK и драйверам заставляют задуматься о том, что на данный момент существуют какие-то проблемы или ошибки, которые пока не удается исправить, то есть продукт все еще находится в стадии бета-тестирования.
Реализация OpenCL для NVidia была достаточно легкой задачей, так как основные идеи сходны: и CUDA и OpenCL – некоторые расширения языка С, со сходным синтаксисом, использующие одинаковую программную модель в качестве основной: Data Parallel (SIMD), так же OpenCL поддерживает Task Parallel programming model – модель, когда одновременно могут выполняться различные kernel (work-group содержит один элемент). О схожести двух технологий говорит даже то что NVidia выпустила специальный документ о том как писать для CUDA так, чтобы потом легко перейти на OpenCL.
Как обстоят дела на настоящий момент
Основной проблемой реализации OpenCL от NVidia является низкая производительность по сравнению с CUDA, но с каждым новым релизом драйверов производительность OpenCL под управлением CUDA все ближе подбирается к производительности CUDA приложений. По заявлениям разработчиков такой же путь проделала и производительность самих CUDA приложений – от сравнительно невысокой на ранний версиях драйверов до впечатляющей в настоящее время.
А что же делала в этот момент AMD? Ведь именно AMD (как сторонник открытых стандартов – закрытый PhysX vs. открытый Havoc; дорогой Intel Thread Profiler vs. бесплатный AMD CodeAnalyst) делала большие ставки на новую технологию, учитывая что AMD Stream не удавалось хоть сколь-нибудь соревноваться в популярности с NVidia CUDA – виною тому отставание Stream от CUDA в техническом плане.
Летом 2009 года компания AMD сделала заявление о поддержке и соответствии стандарту OpenCL в новой версии Stream SDK. На деле же оказалось, что поддержка была реализована только для CPU. Да, именно так, это ничему не противоречит – OpenCL стандарт для гетерогенных систем и ничего не мешает Вам запустить kernel на CPU, более того – это очень удобно в случае если в системе нет другого OpenCL устройства. В таком случае программа будет продолжать работать, только медленнее. Или же вы можете задействовать все вычислительные мощности, которые есть в компьютере – как GPU так и CPU, хотя на практике это не имеет особого смысла, так как время исполнения kernel’ов которые исполняются на CPU будет намного больше тех что исполняются на GPU – скорость процессора станет узким местом. Зато для отладки приложений это более чем удобно.
Поддержка OpenCL для графических адаптеров AMD так же не заставила себя долго ждать – по последним сообщениям компании версия для графических чипов сейчас находится на стадии подтверждения соответствия спецификациям стандарта. После чего она станет доступна всем желающим.
Так как OpenCL должен работать поверх некоторой специфической для железа оболочки, а значит для того чтобы можно этот стандарт действительно стал единым для различных гетерогенных систем – надо чтобы соответствующие оболочки (драйверы) были выпущены и для IBM Cell и для Intel Larrabie. Пока от этих гигантов IT ничего не слышно, таким образом OpenCL остается еще одним средством разработки для GPU на ряду с CUDA, Stream и DirectX Compute.
Заключение
Технология OpenCL представляет интерес для различных компания IT сферы – от разработчиков игр до производителей чипов, а это означает что у нее большие шансы стать фактическим стандартом для разработки высокопроизводительных вычислений, отобрав этот титул у главенствующей в этом секторе CUDA.
В будущем я планирую более подробную статью о самом OpenCL, описывающую что из себя представляет эта технология, ее особенности, достоинства и недостатки.
Спасибо за внимание.