32ビットシステムで-O0
と-O1
という異なる結果を与えるFortranプログラムがあります。プログラムが正確に同じ番号を記入する必要があり変数を格納すると、-O1で簡単な操作の結果が変わります
4.1838698196228139E-013
20.148674000000000
-0.15444754236171612
:このdata
ファイルで
program test
implicit none
character foo
real*8 :: Fact,Final,Zeta,rKappa,Rnxyz,Zeta2
read(5,*) rKappa
read(5,*) Zeta
backspace(5)
read(5,*) Zeta2
read(5,*) Rnxyz
Fact=rKappa/Sqrt(Zeta**3)
write(6,'(ES50.40)') Fact*Rnxyz
Fact=rKappa/Sqrt(Zeta2**3)
Final = Fact*Rnxyz
write(6,'(ES50.40)') Final
end program test
:違いを追跡、私は次のテストケース(test.f90
)を思い付きました。 Zeta2
はZeta
と同じであることに注意してください。同じ番号が再度読み取られるからです(これはコンパイラが同じ番号であり、問題を隠すのを防ぐためです)。唯一の違いは、最初に操作が書き込み時に「オンザフライ」で行われ、結果が変数に保存され、変数が出力されることです。 -O1
とそうでない、番号が同一である-O0
とそう
$ gfortran -O0 -m32 test.f90 && ./a.out < data
-7.1447898573566615177997578153994664188136E-16
-7.1447898573566615177997578153994664188136E-16
$ gfortran -O1 -m32 test.f90 && ./a.out < data
-7.1447898573566615177997578153994664188136E-16
-7.1447898573566605317236262891347096541529E-16
を、:
は、今私はのgfortran 4.8.4(Ubuntuの14.04バージョン)でコンパイルして実行します。
Iは-fdump-tree-optimized
と最適化されたコードを確認しようとした:
final.10_53 = fact_44 * rnxyz.9_52;
D.1835 = final.10_53;
_gfortran_transfer_real_write (&dt_parm.5, &D.1835, 8);
[...]
final.10_63 = rnxyz.9_52 * fact_62;
final = final.10_63;
[...]
_gfortran_transfer_real_write (&dt_parm.6, &final, 8);
私が見る唯一の違いは、一つのケースに印刷数がfact*rnxyz
であることであり、他方ではrnxyz*fact
あります。これは結果を変えることができますか?ハイパフォーマンス・マークスの答えからは、いつどの変数がどのレジスタに行くのかということが関係していると思います。私も-S
で生成されたアセンブリの出力を見てみましたが、私はそれを理解するとは言いません。
そして、(64ビットマシン上)-m32
フラグなしで、番号も同じです...
編集:私は-ffloat-store
または-mfpmath=sse -sse2
を追加した場合の数字が同じである(最後に、hereを参照してください) 。コンパイラがデフォルトで387の計算を使用するので、私がi686マシンでコンパイルするとき、これは理にかなっています。
-mfpmath = SSE [...]
i386のコンパイラの場合:私は
-m32
て、x86-64のマシンでコンパイルする場合でも、それはマニュアルに従って必要とするべきではありませんSSE拡張を有効にしてこのオプションを有効にするには、-march=cpu-type
,-msse
または-msse2
スイッチを使用する必要があります。 x86-64コンパイラの場合、これらの拡張機能はデフォルトで有効になっています。[...]
これは、x86-64のコンパイラのデフォルトの選択肢です。
多分-m32
はこれらの「デフォルト」を無効にしますか?ただし、gfortran -Q --help=target
を実行するとmfpmathは387となり、msse2は無効になります。
アセンブリ生成コードを確認します。 O1は投稿したコードにいくつかの最適化を適用することがあります。さらにhttp://stackoverflow.com/questions/19618679/floating-point-optimizations-guidelineに興味があるかもしれません。 – Harald
@Harald '-S'で出力をチェックしましたが、あまりにも曖昧になり始めました。いずれにしても、私はそこに違いは見られません。私は(AFAICT)関連の部分で質問を更新しています。 – Jellby
@ハラルド私はテストで間違いを犯したので、診断は少し異なります。それは要因の順序の変更があるようです。 – Jellby