簡介
MAC指令的輸入及輸出的
數據類型可以是
整數、
定點數或是
浮點數。若處理浮點數時,會有兩次的
數值修約(Rounding),這在很多典型的DSP上很常見。若一條MAC指令在處理浮點數時只有一次的數值修約,則這種指令稱為“融合乘加運算”/“積和熔加運算”(fused multiply-add, FMA)或“熔合乘法累積運算”(fused multiply–accumulate, FMAC)。
浮點運算中
當使用整數時,操作通常是精確的(以2的冪為單位計算)。 但是浮點數只有一定的數學精度。 也就是說,數字浮點運算通常不是關聯的或分散式的。 (請參閱浮點#精度問題。)因此,無論是使用兩個捨入執行乘法加法,還是使用單個捨入(融合乘法加法)進行一次運算,結果都會產生差異。 IEEE 754-2008規定必須進行一次捨入,才能得到更準確的結果。
積和熔加運算
融合乘加運算的操作和乘積累加的基本一樣,對於浮點數的操作也是一條指令完成。但不同的是,非融合乘加的乘積累加運算,處理浮點數時,會先完成b×c的乘積,將其結果數值修約到N個比特,然後才將修約後的結果與暫存器a的數值相加,再把結果修約到N個比特;融合乘加則是先完成a+b×c的操作,獲得最終的完整結果後方才修約到N個比特。由於減少了數值修約次數,這種操作可以提高運算結果的精度,以及提高運算效率和速率。
積和融加運算可以顯著提升像是這些運算的性能和精度:
積和融加運算通常被依靠用來獲取更精確的運算結果。然而,Kahan指出,如果不假思索地使用這種運算操作,在某些情況下可能會帶來問題。像是
平方差公式
x−
y,它等價於((
x×
x) −
y×
y),若果x與y已知數值,使用積和融加運算來求結果,哪怕
x=
y時,因為在進行首次乘法操作時無視低位的有效比特,可能會使運算結果出錯,如果是多步運算,第一步就出錯則會連累後續的運算結果接連出錯,比如前述的平方差求值後,再取結果的
平方根,那么這個結果也會出錯。
點積指令
一些機器將多個融合乘法加法運算組合成單個步驟,例如, 在兩個128位SIMD暫存器上執行四元素點積a0×b0 + a1×b1 + a2×b2 + a3×b3,具有單周期吞吐量。
支持
FMA操作包含在IEEE 754-2008中。
DEC VAX的POLY指令用於使用一系列乘法和加法步驟來評估具有Horner規則的多項式。指令描述不指定是否使用單個fma步驟執行乘法和加法。[7]該指令自1977年原始的11/780實現以來一直是VAX指令集的一部分。
1999程式語言標準支持通過fma標準數學庫函式進行FMA操作,以及基於FMA控制最佳化的標準編譯指示。
融合的乘法-加法運算是在IBM POWER1(1990)處理器[8]中作為multiply-add融合引入的,但從那時起已被添加到眾多其他處理器中:
HP PA-8000(1996)及以上版本
英特爾安騰(2001)
STI Cell(2006)
富士通SPARC64 VI(2007)及以上
(MIPS兼容)龍芯-2F(2008)
Elbrus-8SV(2018)
帶有FMA3和/或FMA4指令集的x86處理器:
ARM Cortex-M4F(2010)
ARM Cortex-A5(2012)
ARM Cortex-A7(2013)
ARM Cortex-A15(2012)
Qualcomm Krait(2012)
Apple A6(2012)
所有ARMv8處理器
GPU和GPGPU板:
套用到微處理器中的方法
一種微處理器中的方法,用以預備執行一±A*B±C形式的融合乘積62相加運算,其通過傳送第一與第二乘積62相加微指令至一或多個指令執行單元,以完成完整融合乘積62相加運算;第一乘積62相加微指令導引一未捨入非冗餘結果向量、自(a)A與B的部分乘積、或(b)具有A與B部分乘積的C中的一選項的一第一相加運算產生;如果第一相加運算並未包括C,則第二乘積62相加微指令導引具有未捨入非冗餘結果向量的C的一第二相加運算的執行,第二乘積62相加微指令亦導引、自未捨入非非冗餘結果向量產生最終捨入結果,其中,最終捨入結果為融合乘積62相加運算的一完全結果。