2016-04-19 8 views
1

インテルFortranコンパイラでコンパイルするために書かれたFortranコードに問題があります。インテルFortranフォーム= 'バイナリ'の標準同等語

私が持っている具体的な問題はOPENステートメントです。私はフリー・コンパイラ、つまりGNU Fortranでコンパイルできるようにソースコードを書き直そうとしましたが、成功しましたが、いくつか問題があります。

一時ファイル出力はOPEN(access = 'direct', form = 'binary', status = 'replace'...)ですが、form = 'binary'は標準ではなく、GNU Fortranコンパイラではサポートされていません。

Webで解決策を探したところ、form = 'unformatted'は同等でGNU Fortranが対応できることがわかりました。はい、それは本当です、私はコンパイルすることができたとコードが正しく実行されます。しかし、このコードは、このように開いたこれらのファイルに大量のデータを生成する科学的計算です。私の問題は、form = 'unformatted'form = 'binary'の4倍のファイルサイズになるということです。

これでは、フォーマットされていないフォーマットでは正常な実行には十分なハードディスク容量がなく、バイナリでは十分なハードディスク容量がありません。 GNU Fortranで使用可能なインテルFortranのバイナリに相当するファイルがありますか?同様のファイルサイズになりますか?

それは、私は短い、簡略化されたサンプルコードを追加していために頼まれたとおり:

subroutine init 
use module params ! contains param1, param2, param3, ... which are inetger or real 
common /params2/ maxi, maxj, maxk, limit, recnum ! integers defined elsewhere 
real*8, allocatable :: x(:) 
... other variables 
open (unit = 5, file = 'data.txt', access = 'direct', 
* form = 'binary', recl = 16*maxk+8, status = 'replace') 
write(5, rec = 1) param1, param2, param3, maxi, maxj, maxk, limit, recnum ... 
recnum = 2 
do i = 1, maxi 
    do j = 2, maxj 
    ... do some stuff with x 
    write(55, rec=recnum) x(0), (xt(k), xt(limit-k), k = 1, maxk) 
    recnum = recnum + 1 
    done 
done 
close(5) 
end subroutine init 

program xx 
common /params2/ maxi, maxj, maxk, limit, recnum 
... 
call subroutine init 
... 
open (unit = 5, file = 'data.txt', access = 'direct', 
* form = 'binary', recl = 16*maxk+8, status = 'old') 
... do some stuff 
read(5, rec=1) param1, param2, param3, maxi, maxj, maxk, limit, recnum, ... 
... do some stuff 
recnum = 1 
do i = 1, maxi 
    do j = 2, maxj 
    recnum = recnum + 1 
    ... do some stuff 
    read(5, rec=recnum) x(0), (xt(k), xt(limit-k), k = 1, maxk) 
    ... do some stuff 
    done 
done 
close(5) 
end program 

subroutine initによって生成されたファイルdata.txtは、前回の実行から発信私のために最初のレコードの読み取りがprogram xx必要です(実行するたびにsubroutine initの呼び出しが発生しないことがあります)、 と、data.txtのデータを解釈するためにいくつかのパラメータを読み取る必要があります。

このように複数のファイルが生成され、最初のレコードは必ずしも必要ではありません。 私はaccess = streamが必要ではなくても、最初のレコードが読み込まれても動作すると思っています。

しかし、私はaccess = streamaccess = directを交換し、WRITE()またはREAD()reclrec =のすべての発生を削除したとき、私は、ファイルI/Oの間に矛盾のランタイムエラーが発生します。

+0

両方の呼び出しで同じデータ型を保存していますか?実際の書き込みが行われている場所でコードを表示できますか? – Chiel

+0

'binary'と' unformatted'を除いて2つのコードに違いはありません。インテルFortranコンパイラで両方のバージョンをコンパイルしても同じ問題が発生します。 – Balazs

+0

大きなファイルはおそらく多くの書き込みを行い、GNUコンパイラを書き込むたびに、書き込まれたデータのサイズを記述する整数を先頭と末尾に追加することから発生します。 'open'ステートメントに' access = 'stream''を指定すると、あなたはおそらくあなたの問題を解決しました。 – Chiel

答えて

2

私は正確な複製を見つけることができませんでしたが、これまでにここで扱っています。

form='binary' 

は完全に非標準です。標準的な方法は、Cの後にモデル化されており、すべての合理的に最近のコンパイラで使用することができFortran 2003のから標準ストリームへのアクセスを可能にします

access='stream', `form='unformatted' 

を使用することです。

基本的に、form='binary'はそれ以外の言語との互換性はほとんどありませんでした。正しい方法は実際にaccessを変更することです。そのため、おそらくあなたは混乱しているでしょう。

順次アクセスとダイレクトアクセスはすべてレコードベースであり、データに加えてレコードマーカが書き込まれる可能性があります。非標準のform='binary'ではそれが変更されますが、フォーマットされたものとフォーマットされていないものの両方を使用できるストリームアクセスを使用するのが適切な方法です。特に、フォーマットされていないものは非常に便利で、追加のマーカーなしでメモリに保存したバイトを正確に保存しましょう。

+0

ありがとうございます。最後に 'access = 'stream''と' form =' unformatted''で解決できました。ストリームアクセスでは不可能なので、 'recl ='を削除しなければなりません。以前に直接レコード参照で指定されていたとしても、すべてのオープン後にファイルからすべてを読み込むようにしなければなりませんでした。したがって、レコードを選択することは、データが読み取られた後にのみ可能になります。 'stream'の' pos = 'オプションは、私が正しいとすれば、プロセッサ/システムに依存するアクセスにつながる可能性があるので、私はそれを避けました。 – Balazs

+0

pos =はデータサイズに依存します。あなたはそれが移植可能であることを修正したが、実際の種類が何バイトであるかを確認する必要があります。 –

+0

'status = 'replace''を' form =' binary''の振る舞いと同じにするために書くことも指定する必要があります。 –

関連する問題