IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Fortran Discussion :

[Fortran 77] Problème d'écriture dans un fichier : variable "pseudo-NaN"


Sujet :

Fortran

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Août 2003
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 5
    Par défaut [Fortran 77] Problème d'écriture dans un fichier : variable "pseudo-NaN"
    Bonjour à tous,

    Mes excuses d'avance pour ce post qui va etre un peu long, mais le problème que je rencontre n'est pas simple à expliquer.

    Voila, je reprends en ce moment un ancien code en Fortran 77 pour le compléter avec de nouvelles fonctions. Avant cela, j'ai entrepris de le dépoussiérer un peu, et en particulier d'accorder un soin particulier aux declarations de variables, qui étaient toutes faites de manière implicite...

    Le programme consiste à effectuer des calculs à l'intérieur d'une boucle principale, et d'écrire les résultats dans un fichier de sortie à chaque itération.
    Au niveau de la console, le programme est "silencieux" , mis à part qques messages qui signalent que tout se passe bien.

    A l'éxécution, TOUT SE PASSE EFFECTIVEMENT BIEN (les valeurs obtenues en fin de calcul sont vérifées par un moyen parallèle), j'insiste particulièrement sur ce point qui est important pour la suite.
    OR, lorsque j'ouvre mon fichier de sortie j'obtiens ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
         N     OBJ TOT MAX        OBJ TOT MIN        OBJ TOT MOY    
         0     0.500300E+01        0.407003E-05       0.773183E+00
         1     NaN                     NaN                    NaN
         2     NaN                     NaN                    NaN
         3     NaN                     NaN                    NaN
         4     NaN                     NaN                    NaN
         5     NaN                     NaN                    NaN
    Je n'ai mis que les 5 première itérations, mais ca continue comme ca jusqu'au bout.

    La ou ca commence à devenir étrange, c'est que les valeurs affichées sont issues de la variable "object_tot" qui est utilisée telle quelle dans les calculs aux itérations suivantes, donc CE NE SONT PAS DES "VRAIS" NaN, puisque le calcul aboutit normalement. Cela est de plus confirmé par le fait que j'écris un autre fichier de sortie ou la variable "object_tot" est utilisée , et la les valeurs sont correctes.

    Malgré cela, j'ai entrepris, par des WRITE(*,*) successifs, de "pister" l'endroit ou se produit le problème jusqu'à une sous-routine un peu en amont. Mais la le plus étrange se produit :
    Si, à l'intérieur de cette sous-routine, j'écris (pop_size etant la logical size de object_tot):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    DO i=1,pop_size 
          WRITE(*,*) object_tot(i) 
     END DO
    Alors j'obtiens des valeurs correctes pour object_tot, ET LE FICHIER DE SORTIE AFFICHE LES BONNES VALEURS!!!!!
    Autrement dit, un simple "write" de la variable qui pose problème corrige le problème, sans qu'aucune modification portant sur le fonctionnement du code n'ait été réalisée...

    Au final, tout se passe comme si, auniveau interne, les valeurs avaient la bonne valeur (puisque la calcul aboutit normalement), mais que des qu'il s'agit d'affichage (console ou fichier) alors le comportement devient chaotique.
    Vous comprendrez que cet effet "magique" rend le debuggage assez complexe...

    Un dernier détail :
    J'ai déjà rencontré ce problème avec une autre variable, qui, comme "object_tot", est un tableau déclaré avec la taille "pop_size_max" (fixée par une déclaration de type PARAMETER), alors que sa taille "reelle" au cours du calcul est pop_size. Je l'avais alors résolu en veillant à initialiser cette variable à 0 jusqu'à pop_size_max, et non jusqu'à pop_size, ce qui était le cas avant. Mais la meme vérification appliquée à ma variable "object_tot" n'a pas eu ici le meme effet.

    DONC : je m'adresse à vous afin de recueillir vos ipressions sur le sujet, et en particulier, savoir si l'un d'entre vous avait déjà rencontré ce phénomène.
    Sinon, qqn aurait-il une idée de quelle aberration de Fortran pourrait en etre la cause?

    Pour l'instant, je vais garder la version avec sortie de la variable sur console pour pouvoir continuer à avancer, mais lorsque je devrai rendre le projet, il faudra que tout cela soit "propre", donc merci d'avance pour vos réponses.

  2. #2
    Futur Membre du Club
    Profil pro
    Inscrit en
    Août 2003
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 5
    Par défaut
    UPDATE :

    en continuant à trifouiller un peu mon code, je n'ai fait que découvrir des choses toujours plus étranges :

    D'abord, je me suis rendu compte qu'en commentant l'appel à la sous-routine incriminée, le problème disparaissait, signe que "quelquechose" était louche avec celle-ci

    Du coup, j'ai successivement commenté et décommenté certaines lignes de la sous-procédure en question, pour me rendre compte que seule une ligne de code semblait etre à l'origine du problème, puisqu'en commentant cell-ci , tout fonctionnait.
    Problème : cette ligne de code NE FAIT PAS intervenir la variable "object_tot" (meme indirectement)

    Alors j'ai fait des WRITE(*,*) de toutes les variables intervenant dans cette sous-procédure, mais alors je retrouvai l'effet "guérisseur" du WRITE mentionné dans mon premier post.

    Finalement, je me suis rendu compte que ce que j'affichais sur la console avec WRITE N'AVAIT AUCUNE IMPORTANCE. Afficher juste la chaine ' ' (un espace, donc...) suffit à régler le problème. Du coup je me suis dit que le problème venait du nombre de lignes de codes exécutées (je sais c absurde, mais bon...) et j'ai remplacé ce write par une ligne de code "bidon" (style "a=2"), juste pour avoir une ligne de code supplémentaire, mais les NaN réapparaissent.
    Conclusion : il faut que ce soit un WRITE

    Voila, j'ai hate que quelqu'un m'explique ce qu'il se passe, parce que la j'en perds mon latin.

  3. #3
    Modérateur

    Profil pro
    Inscrit en
    Août 2006
    Messages
    974
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Août 2006
    Messages : 974
    Par défaut
    Avec ce que tu dis, le suspect numéro 1 est le passage des paramètres (nombre et type) à ta fonction (ou à une fonction ou sous-routine). Le deuxième suspect est un débordement (adressage d'un tableau en dehors de sa définition).

    Pistes de solution :
    • Enlève l'optimisation et active tous les tests possibles (bound check, ...)
    • Utilise un autre compilateur. Ce genre de problème produit un comportement différent d'un compilateur à l'autre. Tu augmente donc tes chances de trouver l'erreur en augmentant le nombre de manifestations de l'erreur.
    • Vérification manuelle de tous les appels.
    • Tu dis que ton programme est en F77, mais utilises-tu un compilateur F77 ou F95 ? Si c'est F95, tu peux déplacer toutes les fonctions / routines que tu peux dans des modules pour activer la vérification des appels par interfaces explicites. C'est souvent plus rapide qu'une vérification manuelle. Tu peux également saupoudrer des implicite none...

  4. #4
    Futur Membre du Club
    Profil pro
    Inscrit en
    Août 2003
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 5
    Par défaut
    Alors les réponses un peu dans le désordre :

    - J'utilise gfortran comme compilateur et il me semble que c'est un compilateur F95. Par contre, je n'ai aucune expérience de Fortran 95, donc il n'est pas sur que la méthode d'appel automatique que tu proposes soit plus rapide pour moi que la vérification manuelle, puisqu'il faudrait deja que je comprenne comment ca marche....

    - Justement, en parlant de vérification des appels, qu'entends-tu exactement par la?

    - En ce qui concerne les bornes de mes tableaux, j'étais justement en train de me pencher sur le problème, mais en tout cas le problème n'est très probablement pas un dépassement, puisque je déclare mes tableaux avec une taille volontairement très grande par rapport à la taille "réelle" des tableaux pendant le calcul.

    - Comme je suis consciencieux, je vais quand meme vérifier ca, mais à part l'option bounds-check, à quelle autres options de vérification pensais-tu? Parce que j'ai regardé dans la doc de gfortran et j'en ai pas vu d'autres qui semblaient adaptées.


    Ce qui m'embete le plus dans tout ca, c'est pourquoi il ya coexistence entre les "bonnes" valeurs de mes variables (puisque le calcul, une fois de plus, s'effectue tout à fait normalement) et des valeurs NaN dès que WRITE est impliqué (que ce soit sur la console ou dans un fichier)
    Je comprends pas comment c'est possible....

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Août 2003
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 5
    Par défaut
    Ah oui et quel(s) autre(s) compilateur(s) puis-je installer facilement pour tester mon programme dessus?

  6. #6
    Futur Membre du Club
    Profil pro
    Inscrit en
    Août 2003
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 5
    Par défaut
    Et tant qu'on y est , est-ce que quelqu'un aurait l'amabilité de m'expliquer rapidement quelle est la facon la plus propre de passer des tableaux comme arguments d'une sous-routine. Parce que depuis que je cherche des solutions à mon problème, je n'arrete pas de constater que c'est un point épineux.

    Voila comment moi j'ai procédé jusque la :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    program XXXX
     
    implicit none
     
        integer n_step,pop_size,pop_size_max,n_best,n_worst
        parameter (pop_size_max=10000)
        double precision old_obj_tot(pop_size_max),new_obj_tot(pop_size_max),
       *                      new_obj_tot_max,new_obj_tot_min,new_obj_tot_moy         
        ..
        ...
       ....
       ...
       do i=1,n_step
       ..
       call kill_worst(pop_size_max,old_obj_tot,new_obj_tot,n_best,n_worst)
       ..
       ...
       ....
       ...
       ..
       call write_stat_object(new_obj_tot_max,new_obj_tot_min,new_obj_tot_moy)
       .
       end do
    ..
    end program
    Donc ca c'est mon main (restreint aux instructions dont j'ai besoin pour mon exemple), ou la sous-routine kill_worst modifie new_obj_tot à partir des valeurs de old_obj_tot, n_best et n_worst, et la routine write_stat_object écrit des valeurs "statistiques" (type max,min et moyenne) issues de new_obj_tot.

    kill_worst se présente comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
          subroutine kill_worst_vlam(popul_size,old_object_tot,new_object_tot,num_best,num_worst)
     
          implicit none
     
          integer popul_size,num_best,num_worst,
          double precision old_object_tot(popul_size),new_object_tot(popul_size)
     
    c     Variables locales
           integer i,j,ind_best,ind_worst
     
           write(99,*) ' '
    ccc
          do i=1,num_best
                ..
                ...
                new_object_tot(ind_worst)=old_object_tot(ind_best)
                ...
                ..
          end do
     
          end
    (NB : le WRITE(99,*) est le fameux write "magique" qui fait disparaitre les NaN de mes fichiers)

    Est-ce que c'est une manière correcte d'écrire les choses ou pas?

    D'avance merci.

Discussions similaires

  1. problème d'écriture dans un fichier
    Par cartonol dans le forum Oracle
    Réponses: 12
    Dernier message: 17/08/2006, 17h08
  2. [FTP] problème d'écriture dans un fichier
    Par oops! dans le forum Langage
    Réponses: 14
    Dernier message: 08/08/2006, 16h52
  3. problème d'écriture dans un fichier
    Par seurjer dans le forum Langage
    Réponses: 8
    Dernier message: 01/06/2006, 09h15
  4. [PERL] Problème lecture/écriture dans un fichier
    Par LE NEINDRE dans le forum Langage
    Réponses: 4
    Dernier message: 17/08/2005, 13h15
  5. Problème d'écriture dans un fichier xml
    Par vanoou dans le forum C++Builder
    Réponses: 1
    Dernier message: 13/07/2005, 02h28

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo