Умножать и прибавлять: что такое FMA?

18 Окт 2018

В популярных публикациях много слов о «глубоком обучении», причем, с появлением каждого нового функционального расширения, фор­му­ли­ров­ки повторяются снова и снова. Видимо, каждый раз об­уче­ние ста­но­вит­ся еще более глубоким. Между тем, обратившись к документации (и позвав на помощь эмулятор Intel SDE), нетрудно убедиться, что со­став­ными частями для реализации тех­но­ло­гий со столь сложными наз­ва­ни­я­ми являются опе­ра­ции ли­ней­ной ал­ге­б­ры: по­сле­до­ва­тель­но­сти ум­но­же­ний и сложений.

С целью оптимизации машинного кода, необходимого для реализации алгоритмов линейной алгебры, в част­нос­ти, — обработки векторов и матриц, разработано семейство функциональных расширений FMA (Fused Multiply and Add). Именно их применение позволяет комбинировать в одной процессорной инструкции ариф­ме­ти­че­ские дей­ст­вия умножения и сложения. Заметим, что FMA инструкции оперируют числами с плавающей точкой, в то время как функ­ци­о­наль­ное расширение VNNI (Vector Neural Network Instructions) используется для обработки це­ло­чис­лен­ных операндов.

Блок-схема выполнения векторной операции Fused Multiply and Add
Блок-схема выполнения векторной операции Fused Multiply and Add

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

В чем отличие FMA и FMA4

Рассмотрим выражение, вычисление которого достаточно типично для операций линейной алгебры:

Y = X1 * X2 + X3

В трехоперандном варианте (FMA, синоним FMA3 instructions), регистр-получатель результата Y всегда совпадает с одним из трех операндов-источников X1, X2, X3. Поэтому нельзя выполнить операцию, сохранив все регистры-ар­гу­мен­ты неизменными — один из них будет использован для формирования результата и его исходное значение бу­дет по­те­ря­но.

Четырехоперандный вариант (FMA4 instructions) рассчитан на использование четырех независимых операндов, что позволяет сохранить в неприкосновенности содержимое всех аргументов.

Экспериментаторам на заметку

Мнение, согласно которому четырехоперандные FMA-инструкции являются непозволительной роскошью, как пра­ви­ло, ассоциируют с политикой Intel, «репрессировавшей» FMA4-формат. По другой версии, причиной бло­ки­ров­ки является ошибка в дизайне FMA-блока процессоров Ryzen. Вместе с тем, источник заявляет о не­до­ку­мен­ти­ро­ван­ной поддержке и перспективах возрождения (уже в документированном виде) FMA4 в про­цес­со­рах AMD.

Под недокументированной поддержкой в этом контексте понимается ситуация, при которой CPUID-бит, ука­зы­ва­ю­щий на поддержку FMA4, обнулен, но попытка использовать инструкции FMA4 вместо предусмотренной в таком «аварийном» случае генерации исключения по недопустимому коду операции приводит к нормальному ее вы­пол­не­нию.

Экспериментаторы, желающие самостоятельно проверить такой сценарий, должны предусмотреть обработку воз­мож­ных исключений, чтобы избежать аварийного завершения приложения. Кроме того, в силу деликатности си­ту­а­ции, до обретения FMA4-инструкциями официального статуса, нет гарантии, что результат вы­пол­не­ния ока­жет­ся корректным.

О документированных возможностях

Выполним несколько простых проверок, опираясь исключительно на документированную функциональность про­цес­со­ра AMD EPYC 7351 16-Core Processor.

Расширение FMA, в «классической» трехоперандной форме, официально поддерживается процессором AMD EPYC 7351 16-Core Processor, о чем свидетельствует CPUID функция 00000001h, регистр ECX, бит 12
Расширение FMA, в «классической» трехоперандной форме, официально поддерживается процессором AMD EPYC 7351 16-Core Processor, о чем свидетельствует CPUID функция 00000001h, регистр ECX, бит 12

Расширение FMA, в «продвинутой» четырехоперандной форме, официально не поддерживается процессором AMD EPYC 7351 16-Core Processor, о чем свидетельствует CPUID функция 80000001h, регистр ECX, бит 16
Расширение FMA, в «продвинутой» четырехоперандной форме, официально не поддерживается процессором AMD EPYC 7351 16-Core Processor, о чем свидетельствует CPUID функция 80000001h, регистр ECX, бит 16

«Легальные» результаты выполнения инструкции CPUID неожиданностей не принесли: FMA поддерживается, FMA4 — нет. Оценим производительность инструкций FMA.

Цикл вычисления скалярного произведения векторов, по оси X откладывается размер каждого из двух перемножаемых векторов в байтах, по оси Y — производительность в гигабайтах в секунду (около 45.6), исследование в окрестности X = объем кэш-памяти данных L1, работает один поток
Цикл вычисления скалярного произведения векторов, по оси X откладывается размер каждого из двух перемножаемых векторов в байтах, по оси Y — производительность в гигабайтах в секунду (около 45.6), исследование в окрестности X = объем кэш-памяти данных L1, работает один поток

В FMA-тесте утилиты NCRB вычисляется скалярное произведение двух векторов, поэтому адресуется два чи­та­е­мых массива, размер которых в байтах отложен по X. Тест использует формат двойной точности (double precision), одно число занимает 8 байт (64 бита) это необходимо учитывать при пересчете результата в GFLOPS. Одна век­тор­ная 256-битная операция обрабатывает 256 / 64 = 4 операнда. Ввиду наличия двух массивов, теоретический мо­мент переполнения L1 должен иметь место при

X = 32 KB / 2 = 16 KB

При использовании SMT кэш-память каждого ядра обслуживает два потока, поэтому теоретический момент пе­ре­пол­не­ния L1 еще в два раза ниже

X = 16 KB / 2 = 8 KB

Напомним, размер кэш-памяти данных первого уровня процессора AMD EPYC 7351 составляет 32 килобайта.

Время выполнения операции определяется двумя составляющими, первая из которых зависит от времени до­став­ки данных из кэш-памяти, а вторая — не зависит.

  1. Чтение элементов перемножаемых векторов из кэш-памяти в операционный блок.
  2. Вычисления: операции умножения и сложения и манипуляции с данными внутри операционного блока.

Цикл вычисления скалярного произведения векторовб по оси X откладывается размер каждого из двух перемножаемых векторов в байтах, по оси Y — производительность в гигабайтах в секунду (около 733.9), исследование в окрестности X = объем кэш-памяти данных L1; работает 32 потока
Цикл вычисления скалярного произведения векторовб по оси X откладывается размер каждого из двух перемножаемых векторов в байтах, по оси Y — производительность в гигабайтах в секунду (около 733.9), исследование в окрестности X = объем кэш-памяти данных L1; работает 32 потока

Выводы

Начав исследование с документированной формы FMA, мы обнаружили неплохой уровень масштабирования про­из­во­ди­тель­нос­ти. При условии размещения обрабатываемых массивов в кэш-памяти данных первого уровня, со­от­но­ше­ние производительности двух вариантов: с использованием одного логического процессора и всех 32 ло­ги­че­ских процессоров составляет 45.6 к 733.9 что весьма близко к 16. А это, напомним, количество ядер ис­сле­ду­е­мо­го процессора.

Теги: