Question

J'ai ce code fortran 'simplifié'

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

Un des gourous de la programmation m'a averti que fortran accède aux données de manière efficace par ordre de colonne, tandis que c accède aux données de manière efficace par ordre de ligne. Il m'a suggéré de bien regarder le code et de me préparer à changer de boucle pour maintenir la vitesse de l'ancien programme.

Étant le programmeur paresseux que je suis, et reconnaissant les jours d’efforts impliqués et les erreurs que je pourrais faire, je me suis demandé si une technique #define pourrait me permettre de convertir ce code en toute sécurité et facilement.

Avez-vous des suggestions?

Était-ce utile?

La solution

En C, les tableaux multidimensionnels fonctionnent comme suit:

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

En d'autres termes, ce sont des tableaux vraiment plats et [] [] n'est qu'un sucre syntaxique.

Supposons que vous fassiez ceci:

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

Vous parcourez la mémoire de manière séquentielle et vous faites semblant que a et b sont en fait présentés dans l'ordre de la colonne. C'est un peu horrible en ce que un [x] [y]! = À (a, x, y)! = Un [y] [x] , mais à condition que vous vous en souveniez comme ça, tout ira bien.

Modifier

Homme, je me sens idiot. Le but de cette définition est de rendre à (a, x, y) == à [y] [x] , et c'est le cas. Donc, le beaucoup plus simple et facile à comprendre

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

serait mieux que ce que j'ai suggéré ci-dessus.

Autres conseils

Êtes-vous sûr que vos gars de Fortran ont bien fait les choses?

L'extrait de code que vous avez initialement posté accède déjà aux tableaux en ordre de rangée (ce qui est "inefficace" pour FORTRAN, "efficace" pour C).

Comme illustré dans l'extrait de code et comme mentionné dans votre question, obtenir ce "correct" peut être sujet à des erreurs. S'inquiéter de ce que le code FORTRAN soit transféré en C d'abord sans se soucier de détails comme celui-ci. Lorsque le port fonctionne, vous pouvez vous inquiéter de la modification des accès en ordre de colonne en accès en ordre de ligne (si cela a vraiment de l'importance après le fonctionnement du port).

L’un de mes premiers travaux de programmation en dehors du collège a été de réparer une application C de longue durée qui avait été portée de FORTRAN. Les tableaux étaient beaucoup plus grands que le vôtre et cela prenait environ 27 heures par cycle. Après avoir réglé le problème, ils ont fonctionné en deux heures et demie environ… très gentil!

(OK, ce n'était pas vraiment assigné, mais j'étais curieux et j'ai trouvé un gros problème avec leur code. Certains anciens ne m'aimaient pas beaucoup malgré ce correctif.)

Il semblerait que le même problème se retrouve ici.

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

Votre boucle (pour être bon en Fortran) serait:

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

Sinon, vous parcourez les tableaux en rangée majeure, ce qui peut s'avérer extrêmement inefficace.

Au moins, je crois que ce serait la même chose en Fortran - ça fait longtemps.

Vous avez vu le code mis à jour ...

Maintenant, vous voudriez échanger les variables de contrôle de boucle pour pouvoir itérer sur les lignes, puis à l'intérieur de cette itération sur les colonnes si vous convertissez en C.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top