[英]Compiler flags for enhancing the precision of intermediate floating-point calculation
gcc / clang中是否有一個標志指定中間浮點計算的精度?
假設我有一個C代碼
double x = 3.1415926;
double y = 1.414;
double z = x * y;
是否有編譯器標志允許以用戶機器的最高精度計算'x * y',例如,long-double(64位尾數),然后截斷為double(53位尾數,聲明變量類型的精度)?
僅供參考,我在64位計算機上使用Ubuntu 14.04。
GCC
[編輯gcc 4.8.4的觀察行為,其中默認行為與文檔相反]
您需要使用x87 FPU中的80位寄存器。 使用-mfpmath=387
您可以覆蓋SSE寄存器XMM0-XMM7的默認使用。 此默認值實際上為您提供了IEEE行為,其中每個步驟都使用64位寄存器。
請參閱: https : //gcc.gnu.org/wiki/x87note
因此,默認情況下,x87算術不是64/32位IEEE,而是從x87單元獲得擴展精度。 但是,只要將值從寄存器移到IEEE 64或32位存儲單元,就必須將該80位值向下舍入到適當的位數。
但是,如果您的操作非常復雜,可能會發生寄存器溢出; FP寄存器堆棧只有深度8.因此,當溢出復制到字大小的RAM位置時,您將獲得舍入。 您需要在這種情況下自己聲明long double
並在末尾手動舍入,或者檢查匯編器輸出是否顯式溢出。
有關寄存器的更多信息,請訪問: https : //software.intel.com/en-us/articles/introduction-to-x64-assembly
特別是,XMM0 ... 7寄存器雖然128位寬,但只能容納兩個同時進行的64位FP操作。 因此,您希望通過FLD(加載),FMUL(乘法)和FSTP(存儲和彈出)指令查看堆棧操作的FPR寄存器。
所以我編譯了這段代碼:
double mult(double x, double y) {
return x * y;
}
有:
gcc -mfpmath=387 -Ofast -o precision.s -S precision.c
得到了:
mult:
.LFB24:
.cfi_startproc
movsd %xmm1, -8(%rsp)
fldl -8(%rsp)
movsd %xmm0, -8(%rsp)
fldl -8(%rsp)
fmulp %st, %st(1)
fstpl -8(%rsp)
movsd -8(%rsp), %xmm0
ret
.cfi_endproc
現在一切都很完美。 浮點值通過寄存器XMM0和XMM1傳遞(盡管它們必須通過內存進行奇怪的往返才能將它們放到FPR堆棧上),並根據上面的Intel參考在XMM0中返回結果。 不確定為什么沒有直接來自XMM0 / 1的簡單FLD指令,但顯然指令集不這樣做。
如果與-mfpmath=sse
進行比較,則在后一種情況下要做的事情要少得多,因為操作數已准備好並在XMM0 / 1寄存器中等待,並且它就像單個MULSD指令一樣簡單。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.