4

我有一個從VS2013轉換到VS2015期間出現的問題的小例子。在VS2015中進一步提到的代碼示例導致浮點無效操作。VS2015 vs VS2013中的不同優化導致浮點異常

enter image description here

int main() 
{ 
    unsigned int enableBits = _EM_OVERFLOW | _EM_ZERODIVIDE | _EM_INVALID; 

    _clearfp(); 
    _controlfp_s(0, ~enableBits, enableBits); 

    int count = 100; 
    float array[100]; 

    for (int i = 0; i < count; ++i) 
    { 
     array[i] = (float)pow((float)(count - 1 - i)/count, 4); //this causes exception in VS2015 
    } 

    return 0; 
} 

這隻發生在釋放模式因此它可能是由不同的優化所致。這段代碼有什麼問題,或者這是VS 2015中的一個錯誤?

它很難找到像這樣的問題,在整個代碼庫,所以我找一些系統性的修復不是一個解決方法(例如,使用不同的變量,而不是其中工程)

我還檢查產生彙編代碼,它似乎在VS2013中使用整個128位註冊表在一個分區中執行4次浮動操作。在VS2015中,它似乎只做了2次浮動操作,其餘的註冊表都是零(或一些垃圾),這可能會引入此異常。

導致異常的指令被標記在圖片中。

VS2013 VS2013

和VS2015 enter image description here

任何幫助將不勝感激。 謝謝。

+0

嗯。您的代碼適用於啓用了全面優化的我(版本/ x64)。你的VS是最新的嗎?你有什麼「特殊的」編譯器設置? –

+0

我使用VS2015更新3.我使用標準設置進行發佈+優化(最大化速度/ O2)並啓用固有功能(是/否) – Bezousek

回答

1

這看起來是使用浮點異常與您進行的交互,但也啓用了一些浮點優化。

代碼正在做的是它一次執行2次迭代(循環展開),但使用一次4次分割的div(來自XMM寄存器中的4個浮點數)。 XMM寄存器中的高2位浮點數未使用,爲零。由於這些時隙中的值的分配結果不被使用,它通常不重要。然而,當你設置自定義的異常處理時,這會引發一個無效的op異常,即使它的生成值不會被使用。

根據我的理解,您的選擇是設置/ fp:strict,這會禁用優化,因此請使其工作(但顯然會使代碼變慢)或刪除controlfp調用。

+0

感謝您的評論。嚴格的設置將有所幫助,但問題是我不知道應該在哪裏設置它。我通常有數百個計算文件,不想在任何地方減少它。你知道VS2015 vs VS2013會發生什麼,甚至可以在/ fp:精確的情況下運行嗎? – Bezousek