Использовать поддержку экспериментальных устройств в PlaidML?

Я хочу использовать PlaidML для ускорения обучения на моем компьютере Mac Pro. После установки PlaidML я запустил "plaidml-setup" и получил следующее сообщение:

PlaidML Setup (0.3.5)

Thanks for using PlaidML!

Some Notes:
  * Bugs and other issues: https://github.com/plaidml/plaidml
  * Questions: https://stackru.com/questions/tagged/plaidml
  * Say hello: https://groups.google.com/forum/#!forum/plaidml-dev
  * PlaidML is licensed under the GNU AGPLv3

Default Config Devices:
   No devices.

Experimental Config Devices:
   llvm_cpu.0 : CPU (LLVM)
   opencl_amd_amd_radeon_pro_555_compute_engine.0 : AMD AMD Radeon Pro 555 Compute Engine (OpenCL)
   metal_amd_radeon_pro_460.0 : AMD Radeon Pro 460 (Metal)
   opencl_intel_intel(r)_hd_graphics_630.0 : Intel Inc. Intel(R) HD Graphics 630 (OpenCL)
   opencl_cpu.0 : Intel CPU (OpenCL)
   metal_intel(r)_hd_graphics_unknown.0 : Intel(R) HD Graphics Unknown (Metal)

Using experimental devices can cause poor performance, crashes, and other nastiness.

Enable experimental device support? (y,n)[n]:

Почему говорится, что это "экспериментальные устройства"? Это нормально для настройки PlaidML на Mac Pro?

Должен ли я нажать "да", чтобы продолжить настройку?

РЕДАКТИРОВАТЬ: После того, как я нажал "да", мне был представлен другой набор параметров:

Обнаружено несколько устройств (Вы можете переопределить, установив PLAIDML_DEVICE_IDS). Пожалуйста, выберите устройство по умолчанию:

1 : llvm_cpu.0
   2 : opencl_amd_amd_radeon_pro_555_compute_engine.0
   3 : metal_amd_radeon_pro_460.0
   4 : opencl_intel_intel(r)_hd_graphics_630.0
   5 : opencl_cpu.0
   6 : metal_intel(r)_hd_graphics_unknown.0

Default device? (1,2,3,4,5,6)[1]:

Какой я должен выбрать? Или это не имеет значения?

0 ответов

Какую версию macOS вы используете? В каком году машина? Я подозреваю, что для более старых машин или macOS < 10.14 вы не видите значения по умолчанию, потому что PlaidML обратил внимание на то, что Apple отвергла OpenGL/CL в 10.14 в пользу Metal.

FWIW, на моей машине я вижу похожие опции, за исключением того, что металлические устройства перечислены в разделе "Устройства конфигурации по умолчанию".

Что касается каждого из этих вариантов кратко (хорошо, может быть, я увлекся) объяснил:

Вы можете обучать / запускать модели ML на процессорах или графических процессорах. Процессоры не так хорошо подходят для конвейеров математической математики, которые распространены в приложениях ML. Процессоры Moderm имеют потоковые SIMD-расширения (SIMD означает единую инструкцию M- несколько), или SSE. Это позволяет вам выполнять более ограниченный набор операций, подобных матрице. Например, при добавлении двух векторов вместо рассмотрения каждой пары элементов и добавлении их по одному, SIMD позволяет добавлять сразу несколько чисел. Например, компиляция следующего кода с clang -O3 -march=native:

#include <array>

auto add(std::array<float, 64> a, std::array<float, 64> b) {
    std::array<float, 64> output;

    for (size_t i = 0; i < 64; i++) {
        output[i] = a[i] + b[i];
    }

    return output;
}

Мы можем увидеть две разные компиляции в зависимости от того, пройдем ли мы -mno-sse (который, как вы можете догадаться, создает двоичный файл, который работает на процессорах без SSE). С SSE:

add(std::array<float, 64ul>, std::array<float, 64ul>):
        mov     rax, rdi
        vmovups zmm0, zmmword ptr [rsp + 8]
        vaddps  zmm0, zmm0, zmmword ptr [rsp + 264]
        vmovups zmmword ptr [rdi], zmm0
        vmovups zmm0, zmmword ptr [rsp + 72]
        vaddps  zmm0, zmm0, zmmword ptr [rsp + 328]
        vmovups zmmword ptr [rdi + 64], zmm0
        vmovups zmm0, zmmword ptr [rsp + 136]
        vaddps  zmm0, zmm0, zmmword ptr [rsp + 392]
        vmovups zmmword ptr [rdi + 128], zmm0
        vmovups zmm0, zmmword ptr [rsp + 200]
        vaddps  zmm0, zmm0, zmmword ptr [rsp + 456]
        vmovups zmmword ptr [rdi + 192], zmm0
        vzeroupper
        ret

Без SSE:

add(std::array<float, 64ul>, std::array<float, 64ul>):
        mov     rax, rdi
        lea     rcx, [rsp + 264]
        lea     rdx, [rsp + 8]
        xor     esi, esi
.LBB0_1:
        fld     dword ptr [rdx + 4*rsi]
        fadd    dword ptr [rcx + 4*rsi]
        fstp    dword ptr [rax + 4*rsi]
        fld     dword ptr [rdx + 4*rsi + 4]
        fadd    dword ptr [rcx + 4*rsi + 4]
        fstp    dword ptr [rax + 4*rsi + 4]
        fld     dword ptr [rdx + 4*rsi + 8]
        fadd    dword ptr [rcx + 4*rsi + 8]
        fstp    dword ptr [rax + 4*rsi + 8]
        fld     dword ptr [rdx + 4*rsi + 12]
        fadd    dword ptr [rcx + 4*rsi + 12]
        fstp    dword ptr [rax + 4*rsi + 12]
        fld     dword ptr [rdx + 4*rsi + 16]
        fadd    dword ptr [rcx + 4*rsi + 16]
        fstp    dword ptr [rax + 4*rsi + 16]
        fld     dword ptr [rdx + 4*rsi + 20]
        fadd    dword ptr [rcx + 4*rsi + 20]
        fstp    dword ptr [rax + 4*rsi + 20]
        fld     dword ptr [rdx + 4*rsi + 24]
        fadd    dword ptr [rcx + 4*rsi + 24]
        fstp    dword ptr [rax + 4*rsi + 24]
        fld     dword ptr [rdx + 4*rsi + 28]
        fadd    dword ptr [rcx + 4*rsi + 28]
        fstp    dword ptr [rax + 4*rsi + 28]
        add     rsi, 8
        cmp     rsi, 64
        jne     .LBB0_1
        ret

Вам не нужно глубоко понимать, что здесь происходит, но обратите внимание, что инструкции, начинающиеся с v в бинарном SSE. Это инструкции AVX. И zmm0 регистр AVX, который может содержать 16 float s (AVX-512 предоставляет 512-битные регистры, float 32 бита). LLVM использует это преимущество, и вместо добавления чисел элемент за элементом (как мы писали в нашем исходном коде) он делает их по 16 за раз. Вы видите 4 варианта следующей сборки одна за другой (обратите внимание на математику в скобках):

vmovups zmm0, zmmword ptr [rsp + (8 + 64*N)]
vaddps  zmm0, zmm0, zmmword ptr [rsp + (8 + 4*64 + 64*N)]
vmovups zmmword ptr [rdi + (64*N)], zmm0

Здесь математика требует немного знаний о вызове System V ABI. Проще говоря, игнорируйте 8 +, [rsp + 64*N] получает вас a[16*N] в a[16*(N+1)] Эксклюзив. [rsp + (4*64 + 64*N)] пропускает все a (a это 64 floats каждый размером 4 байта) и получает вас b[16*N] в b[16*(N+1)] Эксклюзив. А также [rdi + (64*N)] является output[16*N] в output[16*(N+1)] Эксклюзив. Так что это эффективно переводит на следующий псевдокод:

std::array<float, 16> temp = {a[16*N], a[16*N+1], ..., a[16*N+16]};
temp += {b[16*N], b[16*N+1], ..., b[16*N+16]};
{output[16*n], output[16*N+1], ..., output[16*N+16]} = temp;

Итак, действительно, мы видим, что AVX-512 (расширение SIMD) позволяет нам выполнять сложение по 16 штук за раз. Сравните это быстро с -mno-sse версия. Должно быть ясно, что он делает намного больше работы. Опять же, у нас есть шаблон инструкций (хотя на этот раз он в цикле):

fld     dword ptr [rdx + 4*rsi + 4*N]
fadd    dword ptr [rcx + 4*rsi + 4*N]
fstp    dword ptr [rax + 4*rsi + 4*N]

Есть восемь из них (с N от 0 до 8, эксклюзив). Это оборачивается в цикл, который повторяется 8 раз (8 * 8 = 64, длина массива). Вы должны быть в состоянии угадать, что здесь происходит. Это очень похоже на выше, за исключением того, что мы работаем по одному номеру за раз вместо 16. fld похож на vmovups, fadd похож на vaddps, Псевдокод для этого будет больше похож на код, который мы на самом деле написали:

float temp = a[loop_num*8 + N];
temp += b[loop_num*8 + N];
output[loop_num*8] = temp;

Надеюсь, интуитивно понятно, что гораздо эффективнее будет делать вещи 16 одновременно, чем 1 за раз.

Существуют также причудливые структуры линейной алгебры, такие как blas, которые могут снизить практически всю производительность, которую вы можете получить от процессора, когда дело доходит до математики.

Графические процессоры работают немного по-другому. Грубым упрощением было бы думать о графическом процессоре как о устройстве с огромными SIMD-инструкциями (особенно подходящим для операций с плавающей запятой). Таким образом, вместо того, чтобы работать по 16 за раз, представьте, что вы просто передаете ему изображение целиком, и за одну операцию он может применить к нему пиксельный фильтр (например, изменить яркость или насыщенность).

Так какое отношение имеет эта касательная к чему-либо?

Инструкции AVX делают несколько разумным запуск кода на процессоре. Все варианты, которые вы видите с _cpu в них будет работать только процессор. llvm_cpu вероятно, будет использовать методы, аналогичные вышеупомянутым clang используемый (clang использует llvm за кулисами), чтобы собрать всю математику, необходимую для запуска / тренировки ваших моделей ML. Учитывая, что современные процессоры многоядерные, это может быть как 16 * number_of_cores ускорив.

OpenCL - это открытый стандарт для написания математических вычислений и простого запуска их на различном оборудовании (включая графические процессоры). OpenCL также может эмулироваться процессорами (правда, гораздо медленнее - помните, что процессоры могут делать только 16x, графические процессоры могут делать намного больше).

Металл - замена Apple для OpenGL/CL. Он выполняет аналогичные вещи, но зависит от macOS (и с закрытым исходным кодом).

Единственное различие, которое осталось прокомментировать, это "Intel® R Graphics HD 630" и "AMD Radeon 460". Ваш компьютер имеет два графических процессора. Первая - это встроенная видеокарта. Интегрированный здесь означает, что ваш процессор Intel имеет встроенный небольшой графический процессор. Он не так эффективен, как дискретный графический процессор (отдельный от центрального процессора, который часто встречается в форм-факторах карт для настольных ПК), но он выполняет работу для некоторых менее интенсивных графических задач (и, как правило, более энергоэффективен). Ваш AMD Radeon 460 является дискретным графическим процессором. Скорее всего, это будет самое мощное оборудование для этой задачи.

Исходя из этого, я предсказываю, что устройства будут самыми быстрыми и медленными:

  1. metal_amd_radeon_pro_460.0 - Дискретные графические процессоры работают быстро, Apple оптимизировала Metal, чтобы очень хорошо работать на новых Mac
  2. opencl_amd_amd_radeon_pro_555_compute_engine.0 - Это все еще использует дискретный графический процессор, но OpenCL немного пренебрегли и теперь устарели в macOS, так что, скорее всего, это будет не так быстро
  3. metal_intel(r)_hd_graphics_unknown.0 - Встроенные графические процессоры лучше, чем процессоры, Apple оптимизировала Metal
  4. opencl_intel_intel(r)_hd_graphics_630.0 - то же самое относительно других OpenCL (за исключением того, что это интегрированный, а не дискретный графический процессор)
  5. llvm_cpu.0 - Это использует процессор, но LLVM довольно хорош в написании эффективного кода SIMD.
  6. opencl_cpu.0 - Это эмулирует (2) и (4) за исключением использования вашего процессора, который будет намного медленнее. Кроме того, он, вероятно, не имеет всех причудливых алгоритмов, которые LLVM использует для вывода эффективного кода SIMD.

Но все это предположение, вы можете проверить это pip install plaidbench plaidml-keras keras, Для каждого устройства запустите plainml-setup (выбрав это устройство), а затем запустите plainbench keras mobilenet (или любой другой тест). Вот результаты, которые я вижу на моей машине:


|            device            | exeuction (s) |  fps   | correctness |
|------------------------------|---------------|--------|-------------|
| Metal AMD Radeon Pro 560     |         9.009 | 112.53 | PASS        |
| OpenCL AMD Radeon Pro 560    |        18.339 |  93.29 | PASS        |
| OpenCL Intel HD Graphics 630 |        23.204 |  60.18 | FAIL        |
| Metal Intel HD Graphics 630  |        24.809 |  41.27 | PASS        |
| LLVM CPU                     |        66.072 |  16.82 | PASS        |
| OpenCL CPU Emulation         |       155.639 |   6.71 | FAIL        |

Я переименовал устройства, чтобы они стали красивее, но их сопоставление с идентификаторами должно быть очевидным.

Время выполнения - это время, необходимое для запуска модели (чем ниже, тем лучше), а FPS - это FPS, которого достигло выполнение (чем выше, тем лучше).

Мы отмечаем, что порядок в целом соответствует ожиданиям. Дискретный графический процессор быстрее, чем встроенный графический процессор, который быстрее, чем центральный процессор. Важно отметить, что OpenCL на интегрированной GPU и эмуляции процессора не прошел проверку на правильность. Эмуляция процессора была отключена только примерно в 7%, а встроенный графический процессор был выключен примерно на 77%. Вы, вероятно, хотите выбрать только устройство, которое проходит проверку правильности на вашем компьютере (возможно, но не гарантировано, что серверная часть или само устройство глючат, если оно не проходит эту проверку).

tl; dr Используйте металлический + дискретный графический процессор (AMD Radeon). Это самое быстрое устройство, которое у вас есть. Использование чего-либо на базе процессора только раскручивает ваши вентиляторы и потребляет тонну энергии (и вам понадобится целая вечность, чтобы закончить / тренироваться).

Да, вам абсолютно необходима экспериментальная поддержка для использования PlaidML, и точка. После этого вы хотите выбрать

3: metal_amd_radeon_pro_460.0

или что-нибудь, что говорит "металл" и "radeon" (или NVIVIA, если она у вас есть и она вам больше нравится). Нет смысла использовать графику Intel UHD (даже если вы можете, выбрав6 : metal_intel(r)_hd_graphics_unknown.0), так как уступает дискретному GPU.

Apple отказалась от OpenCL в пользу платформы Apple Metal, и в последнее время в конфигурациях пледов OpenCL появляются ошибки Fail. plaidbench. Например, если вы использовалиopencl водитель, вам будет гарантировано Fail ошибка при запуске

plaidbench keras mobilenet

Вы, скорее всего, получите Success с metal Водитель.

Другие вопросы по тегам