Journal Changer le mode d'arrondi IEEE754 avec roundme

Posté par .
Tags : aucun
6
23
nov.
2009
Bonsoir,

j'ai le plaisir de vous présenter la bibliothèque roundme [https://sourceforge.net/projects/roundme/].
Cette bibliothèque permet de modifier le mode d'arrondi des calculs flottants d'un programme(il faut modifier le code source).

Quel est intérêt de cette bibliothèque par rapport aux classiques fesetround/fegetround disponibles dans la libc (voir fenv.h) ?
De nombreuses fonctions mathématiques (cos, sin, exp, ...) disponibles dans la libm (distribuée avec la libc) ne sont compatibles qu'avec le mode d'arrondi par défaut (au plus proche TONEAREST) sous peine de produire des résultats erronés.
roundme fourni un mécanisme (une série de wrapper) permettant d'intercepter les appels à ces fonctions afin de garantir l'utilisation du mode d'arrondi par défaut pour ces appels.

J'utilise la modification du mode d'arrondi afin de perturber l'exécution des codes de calcul. L'impact de cette perturbation sur les résultats numériques du calcul nous donne une indication sur qualité numérique du code perturbé, sur sa stabilité numérique.

Pour la suite, je souhaite automatiser l'instrumentation de toutes les fonctions d'un code puis utiliser/modifier l'outil bchop [http://kooz.org/rkowen/howto/bchop/article/index.html] afin de détecter les fonctions les plus sensibles d'un code.
  • # roudme

    Posté par . Évalué à 3.

    Salut.

    Bon, je n'ai pas très bien compris a quoi peut servir ta librairie : en gros cela permet d'introduire une erreur dans les calculs pour évaluer la fiabilité des résultats ? Peux tu donner un exemple d'application.

    Et puis j'ai été faire en tour dans le SVN, histoire de voire à quoi peut ressembler un bon vieux code C. Et là je suis tombé sur la fonction "is_chaines_eq". J'espère que ce n'est pas toi qui a écrit ca :-) !
    • [^] # Re: roudme

      Posté par (page perso) . Évalué à 2.

      Peut-être qu'il ne veut pas utiliser strcmp.

      Envoyé depuis mon lapin.

      • [^] # Re: roudme

        Posté par . Évalué à 3.

        En tout cas il ne connait pas le concept de fonction macro pour eviter de dupliquer du code : toutes les fonctions dans math.c sont un copier/coller (indentation identique) à une chaine près...
      • [^] # Re: roudme

        Posté par . Évalué à 10.

        Je pense qu'il fait allusion au nom "is_chaines_eq" qui arrive à combiner autant de problèmes en 13 caractères seulement : mélange anglais/français, abréviation (peu recommandées pour un nom de fonction), et mélange singulier/pluriel.
        • [^] # Re: roudme

          Posté par (page perso) . Évalué à 7.

          Et une fois qu'on a corrigé ça; on peut s'interroger sur la pertinence de réécrire ce qui existe déjà avant de regarder la naïveté touchante de l'algorithme qui scannera toute la chaîne même si le premier caractère diffère...
          • [^] # Re: roudme

            Posté par . Évalué à 10.

            ben quoi, on sait jamais, des fois qu'un caractere dans la suite corrige l'inegalite...
          • [^] # Re: roudme

            Posté par . Évalué à 1.

            Je dois reconnaitre que la flemme de chercher le fameux svn (à l'insu de mon plein gré !) m'a empêché de vérifier mes dires.
        • [^] # Re: roudme

          Posté par . Évalué à 4.

          Sans vouloir enfoncer le clou plus profondément, je faisais allusion à :
          - le nom franglais
          - la duplication effectivement de strcmp
          - aux commentaires parfois en anglais, parfois en francais
          - à une optimisation de boucle triviale et oubliée dans le code
          (aller hop, je balance : http://roundme.svn.sourceforge.net/viewvc/roundme/trunk/src/(...) )

          M'enfin, comme disais mon chef de projet de quand je débutait : "l'important c'est que ca marche"!
          • [^] # Re: rouNdme

            Posté par . Évalué à 8.

            Bonjour et merci pour ces commentaires.

            Je m'attendais au ton piquant des commentaires et je vais m'empresser d'améliorer mon code.

            Allé après réflexion je le dis quand même, j'ai publié cette librairie uniquement pour ne pas la perdre, et pour que vous pointiez les bêtises qu'elle contient donc Merci.
          • [^] # Re: roudme

            Posté par (page perso) . Évalué à 2.

            Je lisais le code source en me disant :
            Je comprend pas, je trouve pas ça si mal... Puis je ne voyais pas de boucle... Et je ne comprenais pas trop cette histoire de strcmp...

            Et puis là j'ai réalisé que je regardais la dernière version commitée du fichier qui tenait compte de tes remarques. Donc pour ceux qui se sont fait avoir comme moi :
            http://roundme.svn.sourceforge.net/viewvc/roundme/trunk/src/(...)

            Au passage, is_chaines_eq est particulièrement moche :

            strlen qui est en o(n) est appelé 2 fois au début pour rien : quand on lit le code on croit en une optimisation du genre : "si la taille diffère, pas la peine de parcourir les chaines" mais strlen a besoin de parcourir les chaines...

            Le code aurait pu se réduire à

            int is_chaines_eq(const char* chaine1, const char* chaine2)
            {
            while (*chaine1 == *chaine2 && *chaine1 != '\0') {
            chaine1++;
            chaine2++;
            }
            return *chaine1 == *chaine2;
            }

            Et tester que chaine1 et chaine2 ne sont pas égales à NULL n'est peut être pas un luxe.

            (et au passage, j'aurais pas mélangé anglais/français)
            • [^] # Re: roudme

              Posté par . Évalué à 1.

              while (*chaine1 == *chaine2 && *chaine1 != '\0') {
              faut aussi tester chaine2, on ne sait pas qui termine en premier!

              exemple : chaine1 : 8 blocs de d'alloué, le '\0' sur le 8em.
              chaine2 : 4 blocs d'alloué, le '\0' sur le 4em :
              avec de la "chance", ca passe (pas de plantage) mais tu lis de la mémoire non alloué...
              normalement (avec electricfence ou autre) -> segfault.


              enfin ca c'est les réminiscence du C que j'ai, je peux me tromper.
              • [^] # Re: roudme

                Posté par . Évalué à 3.

                je me répond à moi même, non effctivement ça passe.

                mea culpa, faut pas que j'écrive si tôt, tous mes neurones ne sont pas connectés.
                • [^] # Re: roudme

                  Posté par (page perso) . Évalué à 2.

                  Ouais l'idée c'est : si l'un se termine avant l'autre, alors ils sont différents et il sort de la boucle.
  • # Calcul par intervalles

    Posté par . Évalué à 8.

    Je sais pas exactement ce que tu souhaites faire, mais ça me fait penser a du calcul par intervalles.

    T'as des libs de calculs qui font du calcul rigoureux en te fournissant des intervalles de flottants comme résultats, dans lesquels le résultat est nécessairement contenu. Elles implémentent l'arithmétique des intervalles de flottants, sont rigoureuses, jouent toutes seules avec l'arrondi des calculs pour encadrer le résultat, et savent faire des calculs sur des intervalles de valeurs et plus seulement des constantes.

    Plus ton calcul est sensible, plus les intervalles résultats risquent d'être grands, a priori.

    Ce sont des outils de bases pour l'analyse par intervalle, et pour la programmation par contraintes sur les réels.

    Quelques liens vers des bibliothèques, entre autre, t'as aussi des implémentations, t'as un projet d'implémentation dans boost :
    http://www.ti3.tu-harburg.de/Software/PROFILEnglisch.html
    http://sourceforge.net/projects/gaol/files/gaol/

    Wikipedia :
    http://en.wikipedia.org/wiki/Interval_arithmetic
    • [^] # Arrondi correct

      Posté par (page perso) . Évalué à 5.

      Si l'objectif est la précision et que le temps de calcul n'est pas un problème : il existe aussi crlibm qui offre un arrondi exact (gère les 4 modes d'arrondi IEEE 754).

      http://www.haypocalc.com/blog/index.php/2009/02/20/188-bibli(...)
      • [^] # Re: Arrondi correct

        Posté par (page perso) . Évalué à 5.

        Ceci dit, si l'objectif est simplement de tester la stabilité d'un code déjà écrit et potentiellement très volumineux, est-ce que la solution proposée par Michel H n'est pas plus simple ? Quoique moins rigoureuse que du calcul par intervalle, il me semble qu'elle permet déjà de se faire une idée rapidement. C'est déjà bien mieux que ce que pratiquent souvent les physiciens en matière de calcul : tant que les résultats ressemblent à ce qui est attendu c'est qu'il ne doit pas y avoir de bogue.
        • [^] # Re: Arrondi correct

          Posté par (page perso) . Évalué à 6.

          Comment, tu ne dis pas comme les autres que ce qu'il fait est nul , stupide, enfantin et inutile ? tu n'as pas peur toi. est-tu vraiment à ta place sur linuxfr ?
          • [^] # Re: Arrondi correct

            Posté par . Évalué à 2.

            Relis les commentaires, il y en a pas beaucoup des "comme ça" ...
            • [^] # Re: Arrondi correct

              Posté par (page perso) . Évalué à 5.

              - jemore +3
              Et là je suis tombé sur la fonction "is_chaines_eq". J'espère que ce n'est pas toi qui a écrit ca :-) !
              - Matthieu C +2
              En tout cas il ne connait pas le concept de fonction macro
              - octabrain +8
              Je pense qu'il fait allusion au nom "is_chaines_eq" qui arrive à combiner autant de problèmes en 13 caractères seulement :
              - dyno partouzeur de drouate +8
              t une fois qu'on a corrigé ça; on peut s'interroger sur la pertinence de réécrire ce qui existe déjà
              - thedude +6
              ben quoi, on sait jamais, des fois qu'un caractere dans la suite corrige l'inegalite...
              - jemore +2
              Sans vouloir enfoncer le clou plus profondément, je faisais allusion à
              - Victor STINNER +4
              Si l'objectif est la précision et que le temps de calcul n'est pas un problème : il existe aussi crlibm
              - Thomas Douillard +6
              Quelques liens vers des bibliothèques, entre autre, t'as aussi des implémentations, ...

              SUR 12 messages , 8 pas vraiment encourageant..
              je sais que 8 sur 12 (dont un de l'auteur) c'est pas beaucoup, mais pour moi ca fait très très beaucoup.
              • [^] # Re: Arrondi correct

                Posté par . Évalué à 4.

                Après cette démonstration plus que convaincante de tes capacités en algèbre «8 sur 12 ca fait très très beaucoup». Je ne peux que te demander d'écrire à ma place la bibliothèque dont j'ai besoin.

                Sinon ben je vais améliorer mon code ainsi que les fonctionnalités qu'il propose en espérant que tu auras :
                * Soit la force de ne pas regarder un code si horriblement laid.
                * Soit l'amabilité de faire des commentaires constructifs pour m'aider à améliorer les choses.

                Bien cordialement
                --
                • [^] # Re: Arrondi correct

                  Posté par (page perso) . Évalué à 7.

                  En fait, si j'ai bien compris le message d'hervé Couvelard, il exprimait un certain agacement devant les commentaires négatifs sur votre code. Pas le contraire.
                • [^] # Re: Arrondi correct

                  Posté par (page perso) . Évalué à 4.

                  >Après cette démonstration plus que convaincante de tes capacités en algèbre «8 sur 12 ca fait très très beaucoup.

                  oui mes intervalles (on dit intervaux?) c'est : rien, presque rien, normal, beaucoup, très beaucoup. Est-ce que roudme pourrait me servir ?

                  je ne sais que répondre.... peut être que l'on ne peut pas être fort en tout, mais là je risque de ne pas être compris. Faisons plus simple : tappez sur la gueule des gens ils préfèrent cela . Si vous les défendez ils se rebiffent.

                  bien cordialement aussi alors.
                  • [^] # Re: Arrondi correct

                    Posté par . Évalué à 2.

                    Désolé pour ma réponse tout à fait stupide, il faut que j'apprenne à lire !

                    Mais Heu, j'msuis vexé a force, m'enfin ça m'apprendra aussi à publier un code sans mettre un casque !

                    En tout cas merci pour les infos issues des commentaires

                    @+
              • [^] # Re: Arrondi correct

                Posté par (page perso) . Évalué à 3.

                Ah oui, critiquer c'est mal et c'est forcément de la méchanceté. De même que l'humour et les conseils ça n'existe pas dans ton monde ? Moi j'y vois de la taquinerie, ce n'est pas méchant. Ils pointent tout de même de vrais problèmes qu'il est important de considérer. Mais il est tout de même possible de mal le prendre.

                Je me demande surtout ce que viennent faire les commentaires de Victor et Thomas là dedans qui sont des invitations à s'intéresser à des concepts proches susceptibles d'intéresser l'auteur du journal.

                Je trouve que leurs commentaires apportent bien plus au débat que les tiens.
              • [^] # Re: Arrondi correct

                Posté par . Évalué à 1.

                heu, perso j'ai fait une blague en reaction a un commentaire, rien de mechant, juste une blague sur un algorithme qui est effectivement assez etonnant. Si encore cette fonction retournait la distance entre les 2 chaines, je dit pas, mais meme pas.

                De meme a l'usage, ou on trouve, des if is_chain_eq() == 1. Ce qui revient sensiblement a ecrire if is_chain_eq == true. Mais pas vraiement en fait, parce que is_chaine_eq pourrait tres bien retourner 2 ou -1, vu que sa signature indique un int en retour.

                La c'est un probleme de design de base.
                Soit is chain eq se contente juste de verifier une (in)egalite, auquel cas elle retourne un boolean, soit elle fait plus que ca (retourne l'ordre relatif) et retourne un int, et l'utiliser pour tester une egalite doit se faire en verifier qu'elle retourne 0 (ce qui est exactement le contraire de ce qu'elle fait, etonnament).

                Prit a l'envers, ca veut dire: si la fonction retourne un bool, elle se contente de verifier l'egalite, si elle retourne un int elle fait plus que l'egalite et donc tester le retour contre 1 pour une egalite est une erreur d'utilisation de la fonction.
                Ou une erreur de design de l'api.

                En l'occurence, c'est une erreur de design de l'api, et ca tombe bien, il l'a change, faut donc croire que les commentaires en question n'etait pas si impertinents.

                Bref, entre ca, le tres mauvais nom, des printf moitie en francais moitie en anglais et l'indentation a la hache ca aide pas a rendre le code lisible, forcement ca fait lever les sourcils, d'ou les critique sur la qualite du code.

                En fait, a zieuter le svn, l'impression que j'ai c'est qu'il a copier coller des bout de code venant d'un autre projet.

                Apres, un coup d'indentation auto, un refactoring sur les nom des fonctions et on en parle plus, ca peut pas faire de mal de lui faire remarquer.
      • [^] # Re: Arrondi correct

        Posté par . Évalué à 4.

        Comme je suis maso, je tente une réponse :

        L'objectif ici, est de fournir un mécanisme rapide (ajout d'un appel dans le code) permettant de donner une idée de la stabilité numérique d'un code.

        Les bibliothèques citées précédemment nécessitent (corrigez moi si je me trompe, mais pas trop fort sur la tête quand même) une réécriture du code en utilisant les instructions de la bibliothèque.
        C'est autrement plus précis mais également irréalisable en un temps raisonnable.

        Donc, j'utilise roundme.
        • [^] # Re: Arrondi correct

          Posté par . Évalué à 4.

          Pour le calcul par intervalle, oui c'est sur, il faudrait sans doute aussi réécrire les expressions à évaluer ou repenser un peu le code.

          Pour la crlibm, je suis déja moins sur, elle a failli être intégrée dans gcc comme biblio mathématique par défaut [1], et j'étais persuadé mais sans source à citer qu'il y avait une lib du même genre intégrée à gcc, dans ce cas ça devrait pas nécessiter de changement dans le code, à voir.

          Mon but c'était juste de montrer des travaux "connexes", pas de te dire ce que tu devais faire, ça fait pas de mal au moins pour la culture, il y a pas de troll ...



          [1] http://www.haypocalc.com/blog/index.php/2009/02/20/188-bibli(...)
        • [^] # Re: Arrondi correct

          Posté par . Évalué à 2.

          Bonjour,

          certaines librairies de calcul par intervalles (celle de BOOST par exemple : [http://www.boost.org/doc/libs/1_37_0/libs/numeric/interval/d(...)]) fonctionnent par surcharge d'opérateurs. Il n'y a donc pas grand chose à changer dans le code, tout juste le type des variables à modifier (un #define devrait faire l'affaire).

          Par contre, ce que tu essaie de faire me fait beaucoup penser au projet CADNA : [http://www-pequan.lip6.fr/cadna/]. Pour résumer, CADNA est une librairie qui estime la stabilité numérique d'un code en modifiant, de manière aléatoire, le mode d'arrondi de chaque opération. Il me semble que CADNA ne demande pas de ré-écrire le code, mais je ne suis pas spécialiste. Tu devrais regarder un peu ce qu'ils font, à mon avis ça peut t'aider.
        • [^] # Re: Arrondi correct

          Posté par . Évalué à 2.

          La bibliothèque en question a l'air d'être mpfr, http://gcc.gnu.org/gcc-4.3/changes.html ...

          J'ai pas très bien compris par contre si les appels à mpfr étaient effectués uniquement pendant la compilation ou aussi dynamiquement à l'exécution, et si tu peux t'en servir pour ton problème.
          • [^] # Re: Arrondi correct

            Posté par (page perso) . Évalué à 4.

            J'ai du mal à suivre cette discussion. Mais sinon quelques infos :

            mpfr fait de l'arrondi correct, comme crlibm, sauf que c'est plus lent. mpfi propose du calcul par intervalle. mpfr et mpfi sont basés sur GMP (nombres entiers), alors que crlibm est basé sur scslib (nombres flottants).

            Le problème du calcul par intervalle est qu'il faut choisir la précision au début du calcul, et que si ça se trouve à la fin l'erreur sera énorme (intervalle trop large). Enfin, c'est LE problème du calcul numérique :-) Mais crlibm, pour les fonctions qu'il offre, est différent car la précision a été précalculée. Alors que libultim utilise toujours 800 bits de précision, ce qui est largement trop la plupart du temps, crlibm utilise juste ce qu'il faut.
            • [^] # Re: Arrondi correct

              Posté par . Évalué à 3.

              En vrai, "le" problème du calcul par intervalle c'est qu'il est pas distributif mais sous distributif : X * (A+B) est inclus dans XA+XB.

              Ca donne des problèmes dans certaines expression, par exemple pour évaluer X-X si X est dans [-1,1]. Si X était un scalaire, on aurait tout le temps x-x=0, mais comme X est un intervalles, le résultat sera surévalué en [-2,2].

              C'est un exemple, ici c'est pas tout a fait pertinent parce qu'on travaille avec des intervalles très petits (à la base c'est des intervalles de largeur nulle, qui risquent de s'aggrandir avec les erreurs), et qu'on peut trivialement s'affranchir du problème, mais c'est pas toujours le cas.

              La conséquence on risque de surestimer l'erreur de calcul, du coup. Pour le fixage de la précision, dans ce contexte c'est pas trop un problème, il suffit de prendre des intervalles à bornes double ou flottantes sachant que les code de calculs utilisent ce genre de représentation, et qu'on fait simplement de l'évaluation d'expression pour estimer, et pas de la résolution de système de contrainte, qui nécessite un peu plus d'outils ... donc pas vraiment de précision a fixer.

              Pour le reste, j'ai relu le lien, et mpfr a l'air de n'être utilisé que pour évaluer les expressions constantes à la compilation.

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.