Небольшое сравнение функционала этих 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.
Что касается DirectX vs OpenGL, то для меня однозначно OpenGL, потому что нет привязки к ОС и есть много расширений от nVidia, которые на DX появляются позже. Сейчас я решил отказаться и от OpenCL, оставив только OpenGL, а дальше в любом случае надо будет переходить на Vulkan.
Комментариев нет:
Отправить комментарий