вторник, 7 февраля 2017 г.

OpenCL vs OpenGL vs CUDA

  Небольшое сравнение функционала этих API для GPGPU. Тестов на производительность не будет, только удобство использования API.

Vulkan
По вулкану читал документацию, но на практике так и не опробовал, но судя по поддержке GLSL и (возможно) OpenCL программ, то разница с ниже перечислеными небольшая.


DirectX
Слишком мало пользовался директ иксом, поэтому не буду ничего писать.


CUDA
Поработал с CUDA я немного, но первые впечатления были крайне положительные:
  • нету разделения на файлы С++ и шейдеров, все пишется в одном файле и может использовать одни и те же типы, это огромный плюс.
  Теперь по недостаткам (относительным):
  • код для GPU компилируется вместе с программой, это уже создает проблемы с совместимостью с другими API, не позволяет в рантайме менять код шейдера и тд, с загрузкой шейдеров в рантайме тоже были проблемы (на тот момент их только-только добавили).
  • у CUDA есть два апи - высокоуровневый, удобный, который пишется вместе с С++ кодом и низкоуровневый, который более совместим с другими API, но при этом значительно сложнее.

OpenCL
OpenCL я использовал несколько лет для своих проектов и причин для этого достаточно:
  • кроссплатформеность.
  • настоящий С с указателями, union, typedef и тд, этот код легко скомпилировать как обычной С и отлаживать на нормальном дебагере.
  • поддержка double и int64, все функции с ними работают, также есть char, short, half, в общем полный набор всех типов данных, можно создавать сэмплер прямо в коде и один image читать с разными сэмплерами.
  • множество точек входа (kernel) в одном шейдере (в Vulkan это добавили для GLSL).
  • много настроек компилятора, много команд препроцессора для оптимизации, я ими почти не пользовался, но в перспективе выглядят полезными.
Теперь недостатки:
  • nVidia поддерживает только 1.2 версию, этого функционала достаточно, но в более новых API возможности поинтереснее.
  • были проблемы с шарингом с OpenGL на AMD, но я снова перешел на nVidia и не стал с этим разбираться. 
  • нет объединения скомпилированных программ (в 2.0 есть), приходится по нескольку раз компилировать один и тот же код в разных шейдерах, но возможность объявлять kernel'ы почти нивелирует этот недостаток.
  • нет перегрузки функций, неудобная конвертация типов (convert_float например), неудобные конструкторы с кучей скобок (например: (int3)(0,0,0)).
  • нет доступа по индексу к компонентам вектора, это заменяется функцией, но все равно не так удобно как в GLSL например.
  • нет функций для матриц, весьма странная особенность, ведь в GLSL они есть и уже оптимизированы, почему нужно писать самому и думать над оптимизацией?

OpenGL compute shaders
Почти все перечисленное относится и к вулкану.
  • не нужно ничего расшаривать, все в одном API.
  • можно объединять скомпилированные шейдеры.
Недостатки:
  • нельзя передавать динамические массивы в функции, получается что массив из shader storage я не могу передать в функцию вообще.
  • double и int64 поддерживает ограниченное количество функций, все остальное надо писать самому, но пока серьезной необходимости в них не было.
  • только одна точка входв в шейдер (main), это не сложно обойти, но неприятно.
  • этот неудобный язык, нет enum и typedef, конструктор массива можно запомнить только если каждый день его писать, долго переносить код с С++ на шейдеры и обратно для отладки, например.
  • memory barrier не очень понятно почему в относительно высокоуровневом OpenGL сделали низкоуровневую синхронизацию, хотя при неправильном использовании я так и не увидил разницы, но никогда не знаешь, когда вылезут баги с многопоточностью, но раз я смог автоматизировать барьеры у себя в фреймворке, то почему это не было сделано в самом OpenGL ?
  • нет настроек по оптимизации кода как в OpenCL (и как в DX), может это следствие высокоуровневости...
  • нельзя объявить сэмплеры прямо в коде как в OpenCL, но для image доступ только по пикселям, для нормализованых координат нужно передавать текстуру. 
  • суффиксы типов вообще неочевидные: F - float, LF - double (long float, серьезно?).
  • зарезервированы слова: uniform, layout, buffer, input, output и тд, некоторые редкие, но например buffer, input, output достаточно популярны... 
  • операторы >, <, == и тд работаю только для скаляров, а функции lessThan, equal и тд - только для векторов, что очень неудобно, когда пишешь "шаблоны".

Итог.
  Если использовать только nVidia и не заботиться о других вендорах, то я бы выбрал CUDA. Может потому что слишком мало использовал и не успел найти существенные недостатки, но удобство в разработке весьма полезно, разве что невозможность править шейдер без перезапуска программы...
  Что касается DirectX vs OpenGL, то для меня однозначно OpenGL, потому что нет привязки к ОС и есть много расширений от nVidia, которые на DX появляются позже. Сейчас я решил отказаться и от OpenCL, оставив только OpenGL, а дальше в любом случае надо будет переходить на Vulkan.

Комментариев нет:

Отправить комментарий