簡體   English   中英

用於增強中間浮點計算精度的編譯器標志

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM