2011-02-10 100 views
4

我必須使用Fortran程序,該程序曾經使用Microsoft Compaq Visual Fortran 6.6進行編譯。我寧願與gfortran一起工​​作,但我遇到了很多問題。 主要問題是生成的二進制文件具有不同的行爲。我的程序需要一個輸入文件,然後必須生成一個輸出文件。但有時候,當使用gfortran編譯的二進制文件時,它會在結束之前崩潰,或者給出不同的數值結果。 這是一個由研究人員使用大量浮點數編寫的程序。Fortran:使用兩種不同的編譯器編譯生成的代碼之間的差異

所以我的問題是:這兩種編譯器之間可能導致這種問題的區別是什麼?

編輯: 我的程序計算了一些參數的值,並且有很多迭代。一開始,一切都很順利。經過多次迭代後,出現了一些NaN值(僅當由gfortran編譯時)。

編輯: 想你大家的答案。 所以我使用了intel編譯器,它通過提供一些有用的錯誤消息來幫助我。 我的問題的起源是一些變量沒有正確初始化。它看起來像使用compaq visual fortran進行編譯時,這些變量將自動將0作爲值,而對於gfortran(和intel),它會使用隨機值,這解釋了在以下迭代中累加的一些數字差異。 所以現在解決方案是更好地理解程序來糾正這些缺失的初始化。

回答

2

這種行爲可能有幾個原因。 我會做的是:

  1. 切斷對所有調試選項中的任何優化

  2. 開關。如果您有權訪問intel編譯器,使用ifort -CB -CU -debug -traceback。如果你必須堅持gfortran,使用valgrind,它的輸出是不太人性化的,但它往往比沒有好。

  3. 確保沒有隱式類型變量,請在所有模塊和所有代碼塊中使用implicit none

  4. 使用一致的浮點類型。我個人總是使用real*8作爲我的代碼中唯一的浮點類型。如果使用外部庫,則可能需要更改某些例程的調用簽名(例如,BLAS對單精度和雙精度變量具有不同的例程名稱)。

如果你很幸運,它只是一些變量沒有被正確初始化,你會通過其中一種技術來捕獲它。否則,正如M.S.B.建議,對程序真正做的事情有更深入的瞭解是必要的。而且,是的,可能需要從您說'有些NaNs值出現'的地方開始手動檢查算法。

2

我不知道崩潰,但英特爾機器中數字代碼的結果的一些差異可能是由於一個編譯器使用80雙打和其他64位雙打,即使不是用於變量,但可能爲臨時值。而且,浮點計算對執行基本操作的順序很敏感。不同的編譯器可能會產生不同的操作順序。

1

不同類型實現的差異,各種非標準供應商擴展的差異可能是很多事情。

這裏只是一些language features that differ的(看gfortran英特爾)。編寫fortran標準的程序在每個編譯器上工作都一樣,但很多人不知道什麼是標準語言功能,以及什麼是語言擴展,因此使用它們......當編譯時遇到不同的編譯器問題時。

如果您將代碼發佈到某處,我可以快速查看它;否則,像這樣,'很難肯定地說。

3

不同的編譯器可以針對相同的源代碼發出不同的指令。如果數值計算在工作邊界上,則一組指令可能工作,而另一組指令可能不工作。大多數編譯器都可以選擇使用更保守的浮點運算,而不是優化速度 - 我建議檢查您正在使用的編譯器選項以用於可用選項。更重要的是,這個問題 - 特別是編譯器同意幾次迭代,但隨後發生分歧 - 可能表明該程序的數值方法是邊界線。簡單的解決方案是提高計算精度,例如從單倍到雙倍。也許還可以調整參數,例如步長或類似參數。更好的做法是更深入地理解算法,並可能做出更根本的改變。

+0

S.B.是否真的有理由使用單精度浮點數? – 2011-02-11 00:50:17