Frage

Ich habe diesen 'vereinfacht' Fortran-Code

real B(100, 200) 
real A(100,200)

... initialize B array code.

do I = 1, 100
  do J = 1, 200
    A(J,I) = B(J,I)
  end do
end do

Einer der Programmierung Gurus warnte mich, dass Fortran greift auf Daten effizient in Spaltenreihenfolge, während c Daten effizient in Reihe, um zugreift. Er schlug vor, dass ich einen guten harten Blick auf den Code zu nehmen und Schleifen hergestellt werden, zu wechseln um die Geschwindigkeit des alten Programms zu erhalten.

Als die faul Programmierer, die ich bin, und die Tage der Mühe erkennen beteiligt, und die Fehler, die ich wahrscheinlich bin zu machen, begann ich frage mich, ob es vielleicht eine #define Technik, die mir diesen Code sicher umwandeln lassen würde, und einfach.

Haben Sie irgendwelche Vorschläge?

War es hilfreich?

Lösung

In C, mehrdimensionale Arrays wie folgt arbeiten:

#define array_length(a) (sizeof(a)/sizeof((a)[0]))
float a[100][200];
a[x][y] == ((float *)a)[array_length(a[0])*x + y];

Mit anderen Worten, sie sind wirklich flach Arrays und [][] nur syntaktischer Zucker ist.

Angenommen, Sie dies tun:

#define at(a, i, j) ((typeof(**(a)) *)a)[(i) + array_length((a)[0])*(j)]
float a[100][200];
float b[100][200];
for (i = 0; i < 100; i++)
    for (j = 0; j < 200; j++)
        at(a, j, i) = at(b, j, i);

Du gehst nacheinander durch Speicher, und so zu tun, dass a und b sind in der Spalte-Großauftrag tatsächlich angelegt. Es ist eine Art schrecklich in diesem a[x][y] != at(a, x, y) != a[y][x], aber so lange wie Sie sich erinnern, dass es so ausgetrickst hat, werden Sie in Ordnung sein.

Bearbeiten

Man, ich fühle mich dumm. Die Absicht dieser Definition ist at(a, x, y) == at[y][x] zu machen, und es tut. So ist das viel einfacher und leichter zu verstehen

#define at(a, i, j) (a)[j][i]

wäre besser, dass das, was ich oben vorgeschlagen.

Andere Tipps

Sind Sie sicher, dass Ihre Fortran Jungs Dinge richtig gemacht haben?

Die Code-Schnipsel Sie ursprünglich bereits gebucht wird, um die Felder in der Reihe-Großauftrag Zugriff (die ‚ineffizient‘ für Fortran, ‚effizient‘ für C ist).

Wie der Code-Snippet veranschaulichte und wie in Ihrer Frage erwähnt, dies immer ‚richtig‘ kann fehleranfällig sein. Sorgen über die Fortran-Code immer zuerst an C portiert, ohne wie diese über Details zu kümmern. Wenn der Port arbeitet -. Dann können Sie sich Sorgen über Spalte-Reihenfolge ändern Zugriffe auf zeilen zugreift, um (wenn es auch wirklich ankommt, nachdem der Port arbeitet)

Eine meiner ersten Programmierung Jobs aus dem College war eine lang andauernde C App zu beheben, die von Fortran portiert worden war. Die Arrays waren viel größer als deins, und es wurde etwas rund 27 Stunden pro Lauf nehmen. Nach dem Fixieren, liefen sie ca. 2,5 Stunden in ... ziemlich süß!

(OK, es ist wirklich nicht zugeordnet war, aber ich war neugierig und ein großes Problem mit ihrem Code gefunden. Einige der alten Zeiten mochten mich nicht viel trotz dieses Updates.)

Es scheint, dass das gleiche Problem hier zu finden ist.

real B(100, 200) 
real A(100,200)

... initialize B array code.

do I = 1, 100
  do J = 1, 200
    A(I,J) = B(I,J)
  end do
end do

Ihr Looping (gut sein Fortran) wäre:

real B(100, 200) 
real A(100,200)

... initialize B array code.

do J = 1, 200
  do I = 1, 100
    A(I,J) = B(I,J)
  end do
end do

Ansonsten marschieren Sie durch die Felder in der Reihe-Dur, die sehr ineffizient sein könnte.

Wenigstens glaube ich, das ist, wie es in Fortran wäre - es ist eine lange Zeit gewesen ist

.

Saw Sie den Code aktualisiert ...

Nun, werden Sie wollen die Schleifensteuerungsvariablen tauschen, so dass Sie in den Zeilen durchlaufen und dann innerhalb dieser Iterierte auf den Säulen, wenn Sie C konvertieren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top