浮點指令的優化

2021-09-05 13:47:32 字數 2960 閱讀 7176

現在的編譯器都能夠針對浮點指令做優化,但是,我還是想你推薦vc,我認為,vc的優化更好,它能夠更好地利用pentium系列處理器的流水線。

· 優化概略

· 盡量理解你的編譯器處理浮點指令的原理,要知道,你不可能把乙個程式完全用浮點指令來寫,更多的**還是基於高階語言的。

· 找出程式的關鍵所在,例如迴圈等**,這些是真正影響效率的地方。

· 分離相關**。

· 注意解決對記憶體頻寬的需求。

· 檢查是否有較長延遲的指令頻繁使用,儘量減少。

· 如果不必要,盡量使用較低的精度。在很多指令操作中,使用較低的精度會獲得較高的速度。這樣也可以節省記憶體。

· 讓你的結果在精度允許的範圍內波動,超過精度範圍的運算將會帶來極大的開銷。

· 善用fxch指令,以優化流水線。

· 在必要的時候展開迴圈,並且重新安排指令的順序。

· 改變資料訪問的模式,盡量使將要訪問的資料位於快取中。

· 提高並行度

pentium ii和pentium iii都只有乙個被流水線化的浮點單元,合理的計算流程可以提高並行度。這樣,你必須知道哪些指令是被流水線化的,一些常用指令的延遲是多少!請看下面的語句:

a = b + c + d;

e = f + g + h;

使用浮點指令可以實現的最簡單的演算法是:

fld b

fadd c

fadd d

fstp a

fld f

fadd g

fadd h

fstp e

在上面的演算法中幾乎每一條指令都依賴於前一指令的計算結果,這將使流水線時斷時續。再來看看下面的演算法:

fld b

fadd c

fld f

fadd g

fxch st(1)

fadd d

fld f

faddp st(1), st

fstp a

fstp e

上面的**使用了fxch指令,這是在浮點優化中很重要的一條指令。fadd的延遲是三個時鐘週期,上面的指令序列幾乎避開了每乙個延遲。

· fxch指令

在pentium ii和pentium iii處理器上,fxch指令的執行沒有附加的時鐘週期的消耗。你可以用它來訪問堆疊深處的元素,這使浮點堆疊的使用更加靈活。

· 迴圈展開

把迴圈展開有以下好處:

· 減少了跳轉的頻率,這樣,跳轉的代價就不那麼明顯了。

· 可以統一編碼,充分利用空閒的暫存器,提高運算速度。

· 更好地安排指令,減少其相關性,有更大的空間去優化流水線的設計,更容易安排指令,使之適應解碼和預取的要求。

迴圈展開並不是僅僅減少了幾個指令,要是想獲得高效能,你有必要重新設計演算法,盡可能去利用更多的資源。

· 浮點指令的延遲

很多浮點指令都有不止乙個時鐘週期的延遲,但是,由於pentium ii和 pentium iii有亂序執行的能力,這些延遲並不一定會很明顯。但是,如果一條指令具有很長的延遲,我們就要重點考慮了。下面就來具體討論一些指令的延遲,及其解決的方法。

· 浮點儲存的延遲

一條浮點指令的儲存操作必須付出乙個額外的時鐘週期去等待它的運算元。在fld之後,fst必須等待乙個時鐘週期;象fmul,fadd這樣的指令,通常是有三個時鐘週期的延遲,而它們後面的fst操作必須等待乙個附加的時鐘週期,也就是說它將忍受四個時鐘週期的延遲。請看下面的例子:

· ; store is dependent on the previous load.

· fld meml ; 1 fld takes 1 clock

· ; 2 fst waits, schedule something here

· fst mem2 ; 3,4 fst takes 2 clocks

· fadd meml ; 1 add takes 3 clocks

· ; 2 add, schedule something here

· ; 3 add, schedule something here

· ; 4 fst waits, schedule something here

· fst mem2 ; 5,2 fst takes 2 clocks

· · ; store is not dependent on the previous load:

· fld meml ; 1

· fld mem2 ; 2

· fxch st(l); 2

· fst mem3 ; 3 stores values loaded from meml

· ; a register may be used immediately after it has

· ; been loaded (with fld):

· fld mem1 ; l

· fadd mem2 ; 2,3,4

· 計算的延遲

一些常用的指令,如fadd, fsub, fmul等,都有三個時鐘週期的延遲,如果你想使用它的計算結果,就至少要在它後面插入兩條指令。

對於一些具有較長時鐘週期延遲的指令如fdiv, fsqrt等指令,就要考慮在它們後面插入整數指令。而且也應當考慮儘量減少這類指令的使用,似乎在任何處理器中,浮點除法都是極其耗費時間的,amd甚至要使用迭代的方法來計算除法和平方根。 

· 整數及浮點乘法

整數的乘法操作如:mul, imul,它們都是在浮點單元中執行的,所以,它們不能和浮點指令平行計算。

儘管浮點乘法的吞吐量為乙個時鐘週期,但是,fmul每兩個時鐘週期才能執行一次,如果你將兩個fmul寫在一起,你將免費獲得乙個時鐘週期的延遲。注意,如果寫成fmul/fxch/fmul的形式,效果也是一樣的。

· 浮點單元的整數運算

盡量避免一些帶有整數引數的浮點指令如:fiadd, fisub。應該把它們分解成兩步來進行:一條fild加上一條相應的浮點指令。fiadd等指令將霸佔流水線四個時鐘週期,而替換以後卻只需占用兩個時鐘週期。

浮點指令的逆向求解

浮點指令的逆向求解 author zfive5 zhaozidong email zfive5 yahoo.com.cn 晚上在csdn上看到乙個給我發過來的乙個浮點運算指令的問題,說實話之前沒有怎樣使用,對它的內部也不是特別清楚,只是業餘時簡單翻過書而已,但靈機一動想到另類求解方法,在vc2005...

浮點運算的優化

比如對於 int x,y y x 1 2 x 2 那麼我們很清楚,編譯器可以將上面的 優化為 y 3 x 1 實際上還會優化為y x 1 x 1 可是如果換成浮點型別呢?比如 double x,y y x 1 2 x 2 呢?這時候,標準編譯選項下面,編譯器不會做任何優化。這個是因為,對於浮點數做的...

常用彙編浮點操作指令

如果不知道st 0 可以看這篇文章 fpu資料暫存器 浮點數載入指令 fld src 將浮點數src壓入st 0 fild src 將整數src壓入st 0 f float 浮點數 i integer 整數 ld load 載入 浮點數儲存指令 fst dst 去浮點數st 0 到dst,不影響棧狀...