В вычислениях , особенно в цифровой обработке сигналов , операция умножения-накопления ( 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-битных SIMD- регистрах a0×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] , но с тех пор была добавлена во многие другие процессоры: