Использовать поддержку экспериментальных устройств в PlaidML? - PullRequest
0 голосов
/ 24 января 2019

Я хочу использовать 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://stackoverflow.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?

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

EDIT: После того как я нажал «да», мне предложили другой набор опций:

Обнаружено несколько устройств (Вы можете переопределить, установив 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]:

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

1 Ответ

0 голосов
/ 15 апреля 2019

Какую версию macOS вы используете?В каком году машина?Я подозреваю, что для более старых машин или macOS <10.14 вы не видите значения по умолчанию, потому что PlaidML прислушался к <a href="https://developer.apple.com/macos/whats-new/" rel="nofollow noreferrer"> отказу Apple от OpenGL / CL в 10.14 в пользу Metal .

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

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

Вы можете обучать / запускать модели ML на процессорах или графических процессорах.Процессоры не так хорошо подходят для конвейеров математической математики, которые распространены в приложениях ML.Процессоры Moderm имеют Потоковые SIMD-расширения (SIMD означает S один I nstruction M ultiple D ata) или 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 с (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, поэтому, скорее всего, он не будет как fast
  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). Это самое быстрое устройство, которое у вас есть. Использование чего-либо на базе процессора будет только раскручивать ваши вентиляторы и потреблять тонну энергии (и на финиш / тренировку уйдет целая вечность).

...