Я спробую узагальнити свій досвід, отриманий в ході розробки ViennaCL, де у нас є CUDA та OpenCL мітки з переважно 1: 1 перекладами багатьох обчислювальних ядер. З вашого запитання я також припускаю, що ми здебільшого тут займаємось графічними процесорами.
Переносність продуктивності.Перш за все, не існує такого поняття, як переносне з продуктивністю ядро в тому сенсі, що ви пишете ядро один раз, і воно буде ефективно працювати на кожному апараті. Не в OpenCL, де це більш очевидно через більш широкий спектр апаратного забезпечення, але також не в CUDA. У CUDA це менш очевидно через менший діапазон апаратного забезпечення, але навіть тут ми маємо розрізняти принаймні три апаратні архітектури (пре-Фермі, Фермі, Кеплер). Ці коливання продуктивності можуть легко призвести до 20-відсоткової зміни продуктивності залежно від того, як ви упорядковуєте потоки та які розміри робочої групи ви вибираєте, навіть якщо ядро настільки просто, як буферна копія. Напевно, варто також згадати, що на GPU pre-Fermi та Fermi можна було швидко записувати ядра множення матриці-матриці безпосередньо в 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 чи обидва внутрішньо. Особисто я ніколи не наважувався б написати код, що замикається на продавця, на те, на що я хочу покластися через кілька років, але цей ідеологічний аспект повинен пройти окрему дискусію.