В вычислительной технике , особенно в цифровой обработке сигналов , операция умножения с накоплением ( MAC ) или умножения с добавлением ( MAD ) является обычным шагом, который вычисляет произведение двух чисел и добавляет это произведение к аккумулятору . Аппаратный блок, который выполняет эту операцию, называется умножителем-аккумулятором ( блок MAC ); сама операция также часто называется операцией MAC или MAD. Операция MAC изменяет аккумулятор a :
При работе с числами с плавающей точкой это может быть выполнено с двумя округлениями (типично для многих DSP ) или с одним округлением. При выполнении с одним округлением это называется слитым умножением-сложением ( FMA ) или слитым умножением-накоплением ( FMAC ).
Современные компьютеры могут содержать выделенный MAC, состоящий из умножителя, реализованного в комбинационной логике, за которым следуют сумматор и регистр-аккумулятор, который хранит результат. Выход регистра подается обратно на один вход сумматора, так что на каждом такте выход умножителя добавляется к регистру. Комбинационные умножители требуют большого объема логики, но могут вычислять произведение гораздо быстрее, чем метод сдвига и сложения, типичный для более ранних компьютеров. Перси Ладгейт был первым, кто задумал MAC в своей Аналитической машине 1909 года [1] и первым, кто использовал MAC для деления (используя умножение, затравленное обратным числом, через сходящийся ряд (1+ x ) −1 ). Первыми современными процессорами, которые были оснащены блоками MAC, были цифровые сигнальные процессоры , но эта техника теперь также распространена в процессорах общего назначения. [2] [3] [4] [5]
При выполнении с целыми числами операция обычно точна (вычисляется по модулю некоторой степени двойки ). Однако числа с плавающей точкой имеют только определенную математическую точность . То есть цифровая арифметика с плавающей точкой, как правило, не является ассоциативной или дистрибутивной . (См. Арифметика с плавающей точкой § Проблемы точности .) Поэтому для результата имеет значение, выполняется ли умножение-сложение с двумя округлениями или за одну операцию с одним округлением (объединенное умножение-сложение). IEEE 754-2008 указывает, что оно должно выполняться с одним округлением, что дает более точный результат. [6]
Совмещенное умножение-сложение ( FMA или fmadd ) [7] — это операция умножения-сложения с плавающей точкой, выполняемая за один шаг ( связанная операция ) с одним округлением. То есть, там, где несвязанное умножение-сложение вычислило бы произведение b × c , округлило бы его до N значащих бит, добавило бы результат к a и округлило бы обратно до N значащих бит, совмещенное умножение-сложение вычислило бы все выражение a + ( b × c ) с полной точностью, прежде чем округлить окончательный результат до N значащих бит.
Быстрый FMA может ускорить и повысить точность многих вычислений, включающих накопление произведений:
Обычно можно положиться на объединенное умножение-сложение, чтобы получить более точные результаты. Однако Уильям Кахан указал, что оно может вызывать проблемы, если используется необдуманно. [8] Если x 2 − y 2 оценивается как (( x × x ) − y × y ) (следуя предложенной Кэханом нотации, в которой избыточные скобки указывают компилятору сначала округлить член ( x × x ) ) с использованием объединенного умножения-сложения, то результат может быть отрицательным, даже когда x = y из-за того, что первое умножение отбрасывает биты с низкой значимостью. Это может привести к ошибке, если, например, затем вычисляется квадратный корень результата.
При реализации внутри микропроцессора FMA может быть быстрее, чем операция умножения с последующим сложением. Однако стандартные промышленные реализации, основанные на оригинальной конструкции IBM RS/6000, требуют 2 N -битного сумматора для правильного вычисления суммы. [9]
Еще одним преимуществом включения этой инструкции является то, что она обеспечивает эффективную программную реализацию операций деления (см. алгоритм деления ) и извлечения квадратного корня (см. методы вычисления квадратных корней ), тем самым устраняя необходимость в выделенном оборудовании для этих операций. [10]
Некоторые машины объединяют несколько объединенных операций умножения и сложения в один шаг, например, выполняя четырехэлементное скалярное произведение на двух 128-битных регистрах SIMDa0×b0 + a1×b1 + a2×b2 + a3×b3
с производительностью одного цикла.
Операция FMA включена в IEEE 754-2008 .
Инструкция VAX корпорации Digital Equipment Corporation (DEC) используется для оценки полиномов с помощью правила Хорнера , используя последовательность шагов умножения и сложения. Описания инструкций не уточняют, выполняются ли умножение и сложение с использованием одного шага FMA. [11] Эта инструкция была частью набора инструкций VAX с момента ее первоначальной реализации 11/780 в 1977 году.POLY
Стандарт языка программирования C 1999 года поддерживает операцию FMA через стандартную библиотечную функцию математики и автоматическое преобразование умножения с последующим сложением (сокращение выражений с плавающей точкой), которое может быть явно включено или отключено с помощью стандартных прагм ( ). Компиляторы GCC и Clang C выполняют такие преобразования по умолчанию для архитектур процессоров, которые поддерживают инструкции FMA. С GCC, который не поддерживает вышеупомянутую прагму, [12] это может глобально контролироваться параметром командной строки. [13]fma()
#pragma STDC FP_CONTRACT
-ffp-contract
Объединенная операция умножения-сложения была введена как «объединенная операция умножения-сложения» в процессоре IBM POWER1 (1990) [14] , но с тех пор была добавлена во множество других процессоров: