Bonjour à tous !
Une question de programmation pas directement propre à Linux ou au logiciel libre mais je ne trouve pas la réponse ailleurs et je sais que des experts en HPC traînent parfois ici, et peut-être ont-ils déjà été confrontés à ce problème. En plus, j’utilise gfortran, bien qu’il ne soit pas le fautif ici.
Je cherche à permuter deux pointeurs (appelons les p1 et p2), ce qui s’écrirait naïvement :
ptemp => p1
p1 => p2
p2 => ptemp
Sauf que ceci ne fonctionne qu’avec un niveau d’optimisation 0 ("-O0" à la compilation).
Le soucis provient du fait que la norme Fortran autorise le terme de droite à contenir une copie temporaire des variables utilisées, et que cette solution peut donc potentiellement faire pointer vers un espace temporaire, perdu par la suite.
Une solution pour d’autres situations consiste à envelopper les assignations dans une subroutine (voir la description d’un bug subtil à ce propos). Avec cette astuce, mon code survit aux niveaux d’optimisation 1 et 2, mais échoue à nouveau pour "-O3". En fait, si le terme de droite peut toujours contenir une copie temporaire, je ne vois pas ce que la solution suggérée apporte, à part qu’en l’enveloppant dans une subroutine, le compilateur est moins tenté de le faire pour optimiser le code.
Du coup, ma conclusion à ce jour est qu’il est impossible de permuter deux pointeurs de manière sûre en Fortran. Je reste toutefois très étonné par ce résultat et attends impatiemment d’être contredit par un expert, car je n’aimerait vraiment pas devoir copier leur contenu, vu la taille de ces tableaux.
Une idée ?
Merci beaucoup de votre aide !
# Quel est l'intéret de la manoeuvre ?
Posté par totof2000 . Évalué à 4. Dernière modification le 10 janvier 2014 à 10:22.
Je suis curieux de savoir pourquoi tu voudrais permuter deux pointeurs. Je ne connais pas Fortran, donc je ne peux pas t'aider, mais par curiosité, j'aimerais savoir ce que tu veux faire.
(Quand on commence à avoir l'habitude des variables à affectations unique, on en vient à se dire que permuter des variables, c'est mal : ça complique le debuggage et le cerveau apprend vite à faire autrement et vient même à oublier l'intéret de ce genre de pratique).
[^] # Re: Quel est l'intéret de la manoeuvre ?
Posté par jyes . Évalué à 1. Dernière modification le 10 janvier 2014 à 11:33.
Je modifie un tableau de grande taille de façon itérative et je ne peux pas faire la modification sur place car les données ne sont pas indépendantes. Du coup, j’ai le tableau aux itérations n et n+1 et après chaque itération, je voudrais les permuter.
Une solution pour éviter de permuter les pointeurs c’est avoir un indice (comme le numéro de l’itération) et de piocher dans le bon tableau en fonction de cet indice. Je finirai par adopter cette solution s’il est effectivement impossible de faire la permutation, mais elle pose plusieurs soucis :
Addendum :
Une solution intermédiaire serait de ne pas permuter les pointeurs mais juste permuter la destination vers laquelle ils pointent (avec a1 et a2 les vrais tableaux) :
Ceci a sûrement plus de chance de survivre à l’optimisation mais ne résout pas le problème décrit dans ma question vis-à-vis de la norme. Car si le terme de droite peut toujours être une copie dans le contexte d’une subroutine, n’importe quelle association de pointeur est dangereuse si elle est faite dans une subroutine et que le pointeur peut être utilisé ailleurs que dans une subroutine appelée depuis celle où a lieu d’assignation. Dans mon cas, ça forcerait à faire l’association dans le programme principal, ce qui va à l’encontre du découpage en subroutine pour la clarté du code.
[^] # Re: Quel est l'intéret de la manoeuvre ?
Posté par totof2000 . Évalué à 2.
Ca me fait vaguement penser à un algorithme de tri … J'avais oublié comment on faisait avec un langage classique :)
Ca veut dire quoi "devenir impures" ? Est-ce un concept propre à Fortran ?
Ca fait plaisir de voir des développeurs qui s'occupent de l'utilisation de la mémoire à l'heure ou tout le monde s'en moque :). Par curiosité, et si ce n'est pas indiscret, pour quelle(s) raison(s) ? Contrainte mémoire réelle ou juste par principe ?
Ca a l'air d'être un langage assez particulier, le Fortran. En tout cas merci pour ces précisions.
[^] # Re: Quel est l'intéret de la manoeuvre ?
Posté par fearan . Évalué à 2.
Pas moi!!! Et je peste après les devs qui s'en moquent, java et son gc ont fait beaucoup de mal de ce point de vu la, et je crains (du moins de ce que je vois actuellement sur le code que je vois) que les pointeurs intelligents en c++ incitent les devs à suivre la même voie que les développeurs java.
pour ce genre de boucle j'aurais plutôt tendance à faire un truc du genre (mon fortran est rouillé je vais plutôt faire du c ;)
Cela me parait plus propre conceptuellement ;)
Il ne faut pas décorner les boeufs avant d'avoir semé le vent
[^] # Re: Quel est l'intéret de la manoeuvre ?
Posté par jyes . Évalué à 1.
Ça revient à écrire les itérations deux par deux. C’est gentil mais en l’occurrence le code en question est une simulation d'écoulement multiphasique turbulent (LES), et les interactions entre les différents modèles sont déjà assez compliquées comme ça au cours d’une seule itération pour je ne multiplie pas par deux les risques d’erreur.
[^] # Re: Quel est l'intéret de la manoeuvre ?
Posté par fearan . Évalué à 2.
Ce que je recommande c'est plutôt qu'avoir une boucle du genre
tant que itération
faire
a
b
c
d
eraif
avoir
tant que iteration
faire
fonction
eraif
avec la fonction qui fait
a
b
c
d
si tu préfères tu peux aussi faire :
C'est juste que j'ai tendance à éviter les tests en coeurs de boucle.
Il ne faut pas décorner les boeufs avant d'avoir semé le vent
# Permutation sans variable intermédiaire
Posté par Claude SIMON (site web personnel) . Évalué à 1. Dernière modification le 10 janvier 2014 à 14:21.
Je n'y connais absolument rien en Fortran, donc ce qui va suivre est peut-être, voire probablement, totalement inapplicable.
Le fait est qu'il y a moyen de permuter deux entiers sans passer par un troisième, avec l'opérateur XOR. En reprenant l'exemple en question, à la sauce C (^ étant l'opérateur XOR bit à bit) :
Suite à une recherche rapide sur le Web, Il semblerait que gfortran ai une opérateur XOR bit à bit ('IEOR', d'après ce que j'ai trouvé). Évidemment, cela ne suffit pas, car, s'il n'est pas possible d'appliquer cet opérateur directement sur des pointeurs (ce qui ne m'étonnerait pas outre mesure), il faut réussir à 'convertir' des pointeurs en entiers (sous condition que ces derniers ai la bonne taille) et vice-versa…
Pour nous émanciper des géants du numérique : Zelbinium !
[^] # Re: Permutation sans variable intermédiaire
Posté par chimrod (site web personnel) . Évalué à 6.
Celui qui me sort un code comme ça à intérêt à mettre un très bon commentaire pour expliquer ces trois lignes !!
[^] # Re: Permutation sans variable intermédiaire
Posté par robin . Évalué à 1.
En fait c'est basé sur le fait que A xor A = A, et que l'ordre des xor n'importe pas. Donc
p2 = p1 ^ p2;
p1 = p2 ^ p1; // p1 = p2 xor p1 xor p2 = p1
p2 = p1 ^ p2; // p2 = p1 xor p1 xor p2 = p2
bépo powered
[^] # Re: Permutation sans variable intermédiaire
Posté par chimrod (site web personnel) . Évalué à 3.
Je connais le principe, mais s'il faut se replonger dans ce code 6 mois après, je pense qu'il me faudra un moment pour comprendre le but de la manœuvre…
[^] # Re: Permutation sans variable intermédiaire
Posté par Zylabon . Évalué à 4.
A xor A = A ? sûr ? :p
Please do not feed the trolls
[^] # Re: Permutation sans variable intermédiaire
Posté par robin . Évalué à 1.
Et mince, A xor A = 0
Dire qu'à la base je voulais donner une explication pour ceux qui ne comprenaient pas. Et je suis tout à fait d'accord qu'il faut mettre un commentaire pour ce genre d'astuce.
bépo powered
[^] # Re: Permutation sans variable intermédiaire
Posté par Sytoka Modon (site web personnel) . Évalué à 2.
Les pointers du Fortran ne sont pas des pointers au sens du C. Tu n'as jamais accès à l'adresse mémoire. On ne les déférence jamais. Ca évite pas mal de chose… mais du coup, pour changer la réfèrence vers laquelle il pointe, on n'utilise pas l'affection = mais l'opération =>
Bref, ce sont plutôt des alias que des pointers…
# Résolu
Posté par jyes . Évalué à 1.
Bon, après un débogage intensif, j’ai trouvé d’autres bugs qui n’avaient rien à voir avec le problème que j’ai décrit. C’est amusant de voir comme des choses qui n’ont rien a voir a priori sont mélangées lors de la compilation et peuvent avoir des interactions complexes à cause de l’optimisation faite par le compilateur.
Mon problème n’est qu’à moitié résolu, car je n’ai pas trouvé de réponse claire vis-à-vis de l’affectation des pointeurs et de la possible copie du terme de droite en Fortran standard. Par contre, gfortran semble maintenant produire un exécutable qui fonctionne bien avec la permutation enveloppée dans des subroutines. Je reste donc sur cette solution pour le moment en croisant les doigts pour qu’un autre compilateur n’ait pas une politique d’optimisation à laquelle cette solution ne survivrait pas.
[^] # Re: Résolu
Posté par lolop (site web personnel) . Évalué à 2.
J'ai déjà eu des problèmes de fonctions C qui ne marchaient plus avec certains niveaux d'optimisation. Ça c'était résolu avec des pragma indiquant au compilateur de ne pas optimiser ces fonctions spécifiquement.
Q? Est-ce qu'il y a de telles options de compilation (en ligne dans le source) en Fortran ?
J'ai trouvé ça:
http://docs.oracle.com/cd/E19957-01/806-3591/E_directives.html
Et cette directive:
C$PRAGMA SUB OPT=n
Sinon, à mon avis tu auras une réponse sur des newgroups comp.lang.fortran ou fr.comp.lang.fortran, où tu as beaucoup plus de chance de trouver des développeurs pointus sur ce langage.
Votez les 30 juin et 7 juillet, en connaissance de cause. http://www.pointal.net/VotesDeputesRN
[^] # Re: Résolu
Posté par Sytoka Modon (site web personnel) . Évalué à 2.
Ceci dis, Fortran évite au maximum les pointeurs et a ajouté pas mal de possibilités via les ALLOCATABLE. Dans de très nombreux cas, cela suffit et pour la performance, c'est 100 fois mieux car les pointeurs sont en général une horreur lorsqu'on veut optimiser un code.
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.