Как CUDA и OpenCL сравниваются друг с другом в конце 2013 года с точки зрения программиста? Моя группа думает о том, чтобы попытаться использовать вычисления на GPU. Будем ли мы значительно ограничивать себя, выбирая оборудование, которое поддерживает только OpenCL, но не CUDA?
Чтобы быть более конкретным, правильны ли следующие предположения?
Все, что возможно в CUDA, возможно и в OpenCL
До тех пор, пока мы не используем библиотеки, данная задача не является значительно легче (или более сложной) в любой из них.
Основным преимуществом CUDA является наличие библиотек
Оба имеют хорошую поддержку для всех трех основных платформ (Win / OSX / Linux)
Ответы:
Я попытаюсь обобщить мой опыт, полученный в ходе разработки ViennaCL, где у нас есть бэкэнды CUDA и OpenCL, в основном с переводами 1: 1 большого количества вычислительных ядер. Из вашего вопроса я также предполагаю, что мы в основном имеем дело с графическими процессорами здесь.
Переносимость производительности.Прежде всего, не существует такого понятия, как переносимые по производительности ядра в том смысле, что вы пишете ядро один раз, и оно будет эффективно работать на любом оборудовании. Не в OpenCL, где это более очевидно из-за более широкого диапазона поддерживаемого оборудования, но также и не в CUDA. В CUDA это менее очевидно из-за меньшего диапазона поддерживаемого аппаратного обеспечения, но даже здесь мы уже должны различать как минимум три аппаратные архитектуры (pre-Fermi, Fermi, Kepler). Эти колебания производительности могут легко привести к 20-процентному изменению производительности в зависимости от того, как вы организовываете потоки и какой размер рабочей группы вы выбираете, даже если ядро так же просто, как буферная копия. Вероятно, также стоит упомянуть, что на графических процессорах до Ферми и Ферми можно было писать быстрые ядра умножения матриц-матриц непосредственно в CUDA, в то время как для последних графических процессоров Kepler кажется, что нужно приблизиться к языку псевдосборки PTX, чтобы приблизиться к производительности CUBLAS. Таким образом, даже у языка, контролируемого поставщиком, такого как CUDA, есть проблемы, чтобы не отставать от аппаратных разработок. Более того, весь код CUDA статически компилируется, когда вы запускаете nvcc, который в некоторой степени требует действия балансировки с помощью флага -arch, в то время как ядра OpenCL компилируются во время выполнения из компилятора "точно в срок", так что вы можете в принципе адаптировать ядра вплоть до самой специфики конкретного вычислительного устройства. Последнее, однако, довольно сложное и обычно становится очень привлекательным вариантом по мере развития вашего кода и накопления опыта. Цена, которую нужно заплатить, - это O (1) время, необходимое для своевременной компиляции, что может быть проблемой в определенных ситуациях. OpenCL 2.
Отладка и профилирование. Инструменты отладки и профилирования CUDA являются лучшими из доступных для GPGPU. Инструменты AMD тоже неплохие, но они не включают в себя такие гемы, как cuda-gdb или cuda-memcheck. Кроме того, до сих пор NVIDIA предоставляет самые надежные драйверы и SDK для GPGPU, зависание системы из-за глючных ядер действительно исключение, а не правило, как для OpenCL, так и для CUDA. По причинам, которые мне, вероятно, не нужно здесь объяснять, NVIDIA больше не предлагает отладку и профилирование для OpenCL с CUDA 5.0 и выше.
Доступность и удобство. Намного проще получить и запустить первые коды CUDA, особенно потому, что код CUDA довольно хорошо интегрируется с кодом хоста. (Я буду обсуждать цену, которую придется заплатить позже.) В Интернете есть множество учебных пособий, а также руководств по оптимизации и некоторых библиотек. С OpenCL вы должны пройти довольно много кода инициализации и записать ваши ядра в строки, поэтому вы обнаружите ошибки компиляции только во время выполнения при передаче исходных кодов в jit-компилятор. Таким образом, требуется больше времени для прохождения одного цикла код / компиляция / отладка с OpenCL, поэтому ваша производительность обычно ниже на этом начальном этапе разработки.
Аспекты библиотеки программного обеспечения. Хотя предыдущие пункты были в пользу CUDA, интеграция в другое программное обеспечение является большим плюсом для OpenCL. Вы можете использовать OpenCL, просто связавшись с общей библиотекой OpenCL, вот и все, в то время как с CUDA вам необходимо иметь весь набор инструментов CUDA. Хуже того, вам нужно использовать правильные компиляторы хоста для работы nvcc. Если вы когда-нибудь пытались использовать, например, CUDA 4.2 с GCC 4.6 или новее, вам будет сложно заставить работать вещи. Как правило, если вы используете какой-либо компилятор, который является более новым, чем CUDA SDK, проблемы могут возникнуть. Интеграция в системы сборки, такие как CMake, является еще одним источником головной боли (вы также можете найти множество доказательств, например, на PETScсписков рассылки). Это может не быть проблемой на вашем собственном компьютере, где вы имеете полный контроль, но как только вы распространите свой код, вы столкнетесь с ситуациями, когда пользователи будут несколько ограничены в своем программном стеке. Другими словами, с CUDA вы больше не можете выбирать свой любимый хост-компилятор, но NVIDIA определяет, какие компиляторы вам разрешено использовать.
Другие аспекты CUDA немного ближе к аппаратному обеспечению (например, перекосам), но мой опыт работы с линейной алгеброй заключается в том, что вы редко получаете от нее существенную выгоду. Для CUDA существует еще несколько программных библиотек, но все больше и больше библиотек используют несколько вычислительных серверных частей. Между тем ViennaCL , VexCL или Paralution поддерживают бэкэнды OpenCL и CUDA, в то же время аналогичная тенденция наблюдается в библиотеках других областей.
GPGPU не Серебряная пуля. Было показано, что GPGPU обеспечивает хорошую производительность для структурированных операций и задач с ограниченными вычислительными возможностями. Однако для алгоритмов с незначительной долей последовательной обработки GPGPU не может волшебным образом преодолеть закон Амдала . В таких ситуациях вам лучше использовать хорошую реализацию ЦП наилучшего доступного алгоритма, чем пытаться создать параллельный, но менее подходящий алгоритм в вашей задаче. Кроме того, PCI-Express является серьезным узким местом, поэтому вам нужно заранее проверить, может ли экономия от графических процессоров компенсировать накладные расходы при перемещении данных вперед и назад.
Моя рекомендация. Пожалуйста, рассмотрите CUDA и OpenCL, а не CUDA илиOpenCL. Не нужно излишне ограничивать себя одной платформой, а вместо этого взять лучшее из обоих миров. Что для меня хорошо, так это настроить начальную реализацию в CUDA, отладить ее, профилировать и затем перенести в OpenCL с помощью простых подстановок строк. (Вы можете даже параметризовать процедуры генерации строк в ядре OpenCL так, чтобы у вас была некоторая гибкость в настройке на целевое оборудование.) Эти усилия по переносу обычно занимают менее 10 процентов вашего времени, но дают вам возможность работать и на другом оборудовании. Вы можете быть удивлены тем, насколько хорошо аппаратное обеспечение не-NVIDIA может работать в определенных ситуациях. Прежде всего, рассмотрите возможность повторного использования функциональности в библиотеках в максимально возможной степени. В то время как быстрый и грязное переопределение некоторых функций часто работает приемлемо для однопоточного исполнения на процессоре, это часто приводит к низкой производительности на массово параллельном оборудовании. В идеале вы можете даже разгрузить все в библиотеки и не заботиться о том, используют ли они CUDA, OpenCL или оба вместе. Лично я бы никогда не осмелился написать код, заблокированный поставщиком, для чего-то, на что я хотел бы рассчитывать через несколько лет, но этот идеологический аспект стоит обсудить отдельно.
источник