2016-04-19 21 views
1

Ich habe ein Problem mit einem Fortran-Code, der für die Kompilierung mit Intel Fortran-Compiler geschrieben wurde.Standard Äquivalent für Intel Fortran Form = 'binär'

Das spezifische Problem, das ich habe, ist mit der OPEN Aussage. Ich habe versucht, den Quellcode neu zu schreiben, damit ich ihn mit einem kostenlosen Compiler, nämlich GNU Fortran, kompilieren kann, und es ist mir gelungen, aber ich habe einige Probleme damit.

Es gibt eine temporäre Dateiausgabe mit OPEN(access = 'direct', form = 'binary', status = 'replace'...), aber form = 'binary' ist kein Standard und wird nicht vom GNU Fortran Compiler unterstützt.

Nach der Suche nach Lösungen im Internet fand ich, dass form = 'unformatted' sollte gleichwertig sein und GNU Fortran kann damit umgehen. Ja, es stimmt, ich konnte kompilieren und der Code läuft einwandfrei. Der Code ist jedoch eine wissenschaftliche Berechnung, die in diesen auf diese Weise geöffneten Dateien eine große Menge an Daten generiert. Mein Problem ist, dass form = 'unformatted' Dateien 4 mal größer als mit form = 'binary' ergibt.

Mit diesem habe ich nicht genug Festplattenspeicher für erfolgreiche Läufe in einigen Fällen mit unformatiertem Format, während mit binären ich hätte. Gibt es eine Entsprechung für Intel Fortran's "binary", die mit GNU Fortran verwendet werden kann und ähnliche Dateigrößen ergibt?

Wie es wurde gefragt, addiere ich einen kurzen, vereinfachte Beispielcode:

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 

Das Lesen des ersten Datensatz ist in program xx notwendig, da die Datei data.txt von erzeugte subroutine init aus einem vorherigen Laufe stammt meinen (Aufruf von subroutine init möglicherweise nicht bei jedem Lauf), und einige Parameter müssen gelesen werden, um Daten in data.txt zu interpretieren.

Mehrere Dateien werden so generiert und der erste Datensatz wird nicht immer benötigt. Ich nehme an, access = stream könnte funktionieren, wenn der erste Datensatz gelesen wird, auch wenn es nicht notwendig ist.

Aber wenn ich ersetzen access = direct mit access = stream und entfernen recl und jedes Vorkommen von rec = in WRITE() oder READ() ich Laufzeitfehler der Inkonsistenz während Datei-I/O erhalten.

+0

Speichern Sie den gleichen Datentyp in beiden Aufrufen? Können Sie Ihren Code dort anzeigen, wo die tatsächlichen Schreibvorgänge ausgeführt werden? – Chiel

+0

Es gibt keinen Unterschied in den zwei Codes mit Ausnahme des 'binären' gegenüber 'unformatierten' Austauschs. Ich bekomme das gleiche Problem, auch wenn ich beide Versionen mit Intel Fortran Compiler kompiliere. – Balazs

+0

Die größere Datei ergibt sich wahrscheinlich aus der Tatsache, dass Sie viele Schreibvorgänge durchführen und bei jedem Schreiben des GNU-Compilers eine Ganzzahl am Anfang und Ende hinzufügt, die die Größe der geschriebenen Daten beschreibt. Wenn Sie der Anweisung 'open' einen 'access =' ​​stream 'zur Verfügung stellen, haben Sie wahrscheinlich Ihr Problem gelöst. – Chiel

Antwort

2

Ich konnte kein genaues Duplikat finden, wurde aber hier schon behandelt.

form='binary' 

ist vollständig nicht Standard. Der übliche Weg ist

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

zu verwenden, die den Standard-Stream Zugriff von Fortran 2003 ermöglicht es, die nach C modelliert und kann in allen einigermaßen letzten Compiler verwendet werden.

Grundsätzlich war die form='binary' nicht sehr kompatibel mit dem Rest der Sprache. Der richtige Weg ist, wirklich die access zu ändern, deshalb sind Sie wahrscheinlich verwirrt.

Der sequentielle und direkte Zugriff erfolgt auf Datensatzbasis und kann dazu führen, dass zusätzlich zu Ihren Daten auch Datensatzmarker geschrieben werden. Der nicht standardmäßige form='binary' ändert das, aber der richtige Weg besteht darin, den Stream-Zugriff zu verwenden, der sowohl formatiert als auch unformatiert sein kann.Besonders das Unformatierte ist sehr praktisch und Sie können genau die Bytes, die Sie im Speicher haben, ohne zusätzliche Markierungen speichern.

+0

Danke. Endlich konnte ich mit 'access = 'stream' und' form =' unformatted' lösen. Ich musste 'recl =' entfernen, weil es mit Stream-Zugriff nicht möglich ist, und ich musste sicherstellen, dass nach jedem Öffnen alles aus einer Datei gelesen wird, auch wenn es zuvor durch direkte Datensatzreferenz angegeben wurde. Die Auswahl eines Datensatzes wäre daher erst nach dem Lesen der Daten möglich. Die 'pos =' Option von 'stream' könnte zu einem prozessor/systemabhängigen Zugriff führen, wenn ich richtig bin, also habe ich das vermieden. – Balazs

+0

Die pos = hängt von Ihren Datengrößen ab. Wenn Sie beheben, dass es portabel ist, aber Sie müssen sicher sein, wie viele Bytes Ihre wahre Art zum Beispiel ist. –

+0

müssen Sie auch 'status = 'replace'' zum Schreiben angeben, um es dem' form =' binary'-Verhalten gleichzusetzen. –