コンピューティング、特にデジタル信号処理において、乗算加算(MAC)または乗算加算(MAD)演算は、2つの数値の積を計算し、その積をアキュムレータに加算する一般的なステップです。この演算を実行するハードウェアユニットは乗算加算器(MACユニット)として知られており、演算自体もMAC演算またはMAD演算と呼ばれることがよくあります。MAC演算はアキュムレータaを変更します。
浮動小数点数を扱う場合、2回の丸め(多くのDSPで一般的)または1回の丸めで実行できます。1回の丸めで実行される場合、それは融合乗算加算(FMA)または融合乗算累積(FMAC )と呼ばれます。
現代のコンピュータには、組み合わせ論理で実装された乗算器、加算器、および結果を格納するアキュムレータレジスタで構成される専用のMACが搭載されている場合があります。レジスタの出力は加算器の1つの入力にフィードバックされるため、クロックサイクルごとに乗算器の出力がレジスタに追加されます。組み合わせ乗算器は大量のロジックを必要としますが、初期のコンピュータで一般的だったシフトと加算の方法よりもはるかに高速に積を計算できます。パーシー・ラドゲートは、1909年の解析マシンでMACを最初に考案し[ 1 ]、MACを除算に初めて利用しました(収束級数(1+ x ) -1を介して逆数でシードされた乗算を使用)。MACユニットを搭載した最初の現代のプロセッサはデジタル信号プロセッサでしたが、この技術は現在では汎用プロセッサでも一般的です。[ 2 ] [ 3 ] [ 4 ] [ 5 ]
整数で演算を行う場合、通常は正確な値が得られます(2のべき乗を法として計算されます)。しかし、浮動小数点数には一定の数学的精度しかありません。つまり、デジタル浮動小数点演算は一般的に結合法則や分配法則を満たしません。(浮動小数点演算§精度の問題を参照)。そのため、乗算加算を2回の丸めで実行するか、1回の丸めで1回の演算(融合乗算加算)で実行するかによって結果が異なります。IEEE 754-2008では、より正確な結果を得るために、1回の丸めで実行する必要があると規定されています。[ 6 ]
融合乗算加算(FMAまたはfmadd ) [ 7 ]は、1回の丸めで1ステップ(融合演算) で実行される浮動小数点乗算加算演算です。つまり、非融合乗算加算では積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設計に基づく標準的な産業用実装では、合計を正しく計算するために2Nビット加算器が必要です。 [ 9 ]
この命令を含めることのもう1つの利点は、除算(除算アルゴリズムを参照)と平方根(平方根の計算方法を参照)の演算を効率的にソフトウェアで実装できるため、これらの演算専用のハードウェアが不要になることです。[ 10 ]
一部のマシンでは、複数の積和演算を1つのステップに統合しており、例えば、2つの128ビットSIMDレジスタに対して4要素のドット積をa0×b0 + a1×b1 + a2×b2 + a3×b31サイクルで実行できます。
FMAの動作はIEEE 754-2008に含まれています。
C プログラミング言語の1999 年標準は、標準数学ライブラリ関数と乗算の後に加算を行う自動変換 (浮動小数点式の縮約) を介してFMA 演算をサポートしており、これは標準プラグマ ( ) で明示的に有効または無効にすることができます。GCCおよびClang C コンパイラは、FMA 命令をサポートするプロセッサ アーキテクチャに対して、デフォルトでこのような変換を実行します。前述のプラグマをサポートしていない GCC では、[ 11 ]コマンドライン オプションでこれをグローバルに制御できます。[ 12 ]fma()#pragma STDC FP_CONTRACT-ffp-contract
融合乗算加算演算は、IBM POWER1 (1990) プロセッサで「融合乗算加算」として導入されましたが、 [ 13 ]多くのプロセッサに追加されています。
GPUおよびGPGPUボード:
MADD のより単純な実装では、加算前に乗算の結果を切り捨てます。これは精度上の利点はなく (実際には精度が低くなります)、2010 年以前は、正確な FMA よりも GPU でより一般的にサポートされていました。例として、Nvidia PTX の「FMAD」命令が挙げられます。[ 18 ]
OpenCL の最適化オプションを使用すると、OpenCL 1.0 で同等の式を「精度を下げて」計算する関数を に-cl-mad-enable置き換えることができます。 [ 19 ]このオプションと の精度は、OpenCL の新しいバージョンでより微妙になり、バージョン 3.0 以降では「組み込みプロファイル」でのみ精度を下げることができます。[ 20 ]a * b + cmad(a, b, c)mad()
デジタル機器コーポレーション(DEC) VAXのPOLY命令は、乗算と加算のステップを連続して使用して、ホーナーのルールで多項式を評価するために使用されます。命令の説明では、乗算と加算が単一の FMA ステップで実行されるかどうかは指定されていません。この命令は、1977 年の最初の 11/780 実装以来、VAX 命令セットの一部となっています。[ 21 ]ボブ・サプニックによると、マシンは内部で乗算と加算を拡張精度で実行し、ターゲット形式に変換します。[ 22 ]そのため、乗算の後に丸めステップがあります。結果として、この操作はターゲット形式で単純な操作よりも精度が高いもののa * b + c、IEEE の FMA の定義を満たしていません。
この動作は、x87FLT_EVAL_METHOD == 2上で使用した場合と類似しています。