Domanda

Ho questo codice fortran "semplificato"

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

Uno dei guru della programmazione mi ha avvertito che fortran accede ai dati in modo efficiente nell'ordine delle colonne, mentre c accede ai dati in modo efficiente nell'ordine delle righe. Mi ha suggerito di dare una buona occhiata al codice e di essere pronto a cambiare loop per mantenere la velocità del vecchio programma.

Essendo il programmatore pigro che sono, e riconoscendo i giorni di sforzo coinvolti e gli errori che probabilmente farò, ho iniziato a chiedermi se potesse esistere una tecnica #define che mi permetta di convertire questo codice in modo sicuro e facile.

Hai qualche suggerimento?

È stato utile?

Soluzione

In C, le matrici multidimensionali funzionano in questo modo:

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

In altre parole, sono matrici davvero piatte e [] [] è solo zucchero sintattico.

Supponi di fare questo:

#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);

Stai camminando in sequenza attraverso la memoria e fingendo che a e b siano effettivamente disposti in ordine di colonna maggiore. È un po 'orribile in quel a [x] [y]! = At ??(a, x, y)! = A [y] [x] , ma finché ricordi che è stato eliminato così, starai bene.

Modifica

Amico, mi sento stupido. L'intenzione di questa definizione è fare in (a, x, y) == at [y] [x] , e lo fa. Quindi molto più semplice e facile da capire

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

sarebbe meglio di quello che ho suggerito sopra.

Altri suggerimenti

Sei sicuro che i tuoi ragazzi FORTRAN abbiano fatto le cose bene?

Lo snippet di codice originariamente pubblicato sta già accedendo alle matrici nell'ordine delle righe principali (che è "inefficiente" per FORTRAN, "efficiente" per C).

Come illustrato dallo snippet di codice e come indicato nella tua domanda, ottenere questo "corretto" può essere soggetto a errori. Preoccupati di portare prima il codice FORTRAN su C senza preoccuparti di dettagli come questo. Quando la porta funziona, allora puoi preoccuparti di modificare gli accessi all'ordine delle colonne agli accessi all'ordine delle righe (se è davvero importante dopo che la porta funziona).

Uno dei miei primi lavori di programmazione fuori dal college è stato quello di riparare un'app C di lunga durata che era stata trasferita da FORTRAN. Gli array erano molto più grandi dei tuoi e impiegavano circa 27 ore a corsa. Dopo averlo riparato, hanno funzionato in circa 2,5 ore ... piuttosto dolce!

(OK, in realtà non è stato assegnato, ma ero curioso e ho riscontrato un grosso problema con il loro codice. Alcuni dei vecchi timer non mi piacevano molto nonostante questa correzione.)

Sembra che lo stesso problema sia stato trovato qui.

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

Il tuo loop (per essere un buon FORTRAN) sarebbe:

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

Altrimenti stai marciando attraverso le matrici in fila maggiore, il che potrebbe essere altamente inefficiente.

Almeno credo che sia così in FORTRAN - è passato molto tempo.


Ti ho visto aggiornato il codice ...

Ora, si desidera scambiare le variabili di controllo del ciclo in modo da iterare sulle righe e quindi all'interno di quelle iterate sulle colonne se si sta convertendo in C.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top