2010-02-26 4 views
3

Je fais quelques calculs numériques, et j'ai souvent eu des problèmes avec les calculs à virgule flottante lors de l'utilisation de GCC. Pour mon but actuel, je ne me soucie pas trop de la vraie précision des résultats, mais je veux cette propriété ferme:Comportement constant du code flottant avec GCC

peu importe où le code SAME est dans mon programme, lorsqu'il est exécuté sur les entrées SAME , Je veux qu'il donne les mêmes résultats.

Comment puis-je forcer GCC à faire cela? Et plus précisément, quel est le comportement de --fast-math, et les différentes -O optimisations? J'ai entendu dire que GCC pourrait essayer d'être intelligent, et parfois charger des flottants dans les registres, et parfois les lire directement depuis la mémoire, et que cela pourrait changer la précision des flottants, résultant en une sortie différente. Comment puis-je éviter ça?

Encore une fois, je veux:

  • mes calculs pour être rapide
  • mes calculs fiables (c.-même entrée -> même résultat.)
  • Je ne me soucie pas beaucoup au sujet de la précision pour ce code particulier, donc je peux être bien avec une précision réduite si cela apporte la fiabilité

quelqu'un pourrait-il me dire quelle est la voie à suivre pour ce problème?

Répondre

-1

Je pense que GCC est assez bien documenté donc je ne vais pas révéler ma propre ignorance en essayant de répondre aux parties de votre question sur ses options et leurs effets. Je ferais, cependant, l'affirmation générale que lorsque la précision numérique et la performance sont concernés, il est très payant de lire le manuel.Les gens intelligents qui travaillent sur GCC mettent beaucoup d'efforts dans leur documentation, la lire est gratifiante (OK, ça peut être un peu terne, mais bon, c'est un manuel de compilation pas un corsaire-ripper).

S'il est important pour vous que vous obteniez des résultats numériques identiques au dernier bit, vous devrez vous préoccuper de bien plus que GCC et de la façon dont vous pouvez contrôler son comportement. Vous devrez verrouiller les bibliothèques qu'il appelle, le matériel sur lequel il fonctionne et probablement un certain nombre d'autres facteurs auxquels je n'ai pas encore pensé. Dans le pire des cas (?) Vous pouvez même, et j'ai vu cela, écrire vos propres implémentations de maths f-p pour garantir l'identité des bits sur toutes les plates-formes. Ceci est difficile, et donc coûteux, et vous laisse peut-être moins sûr de l'exactitude de votre propre code que du code usd de GCC.

Cependant, vous écrivez

Je ne me soucie pas beaucoup sur la précision de ce code particulier, donc je peux être très bien avec une précision réduite si cela apporte une fiabilité

qui invite la question à vous - pourquoi n'utilisez-vous pas simplement la précision à 5 décimales comme standard de précision (réduite)? C'est ce que beaucoup d'entre nous en informatique numérique font tout le temps; nous ignorons les aspects les plus subtils de l'analyse numérique car ils sont difficiles, et coûteux en temps de calcul, à contourner. Je pense à des choses comme l'arithmétique des intervalles et les mathématiques de haute précision. (Bien sûr, si 5 n'est pas bon pour vous, choisissez un autre nombre à un chiffre.)

Mais la bonne nouvelle est que cela est tout à fait justifiable: nous avons affaire à des données scientifiques qui, par nature, viennent avec erreurs jointes (bien sûr, nous ne savons généralement pas quelles sont les erreurs, mais c'est une autre affaire), il est donc possible de ne pas tenir compte des derniers chiffres de la représentation décimale, disons, d'un nombre fp de 64 bits. Allez droit devant et ignorez un peu plus d'entre eux. Mieux encore, peu importe le nombre de bits de vos numéros f-p, vous perdrez toujours une certaine précision en effectuant des calculs numériques sur les ordinateurs; ajouter plus de bits repousse simplement les erreurs, à la fois vers les bits les moins significatifs et vers la fin des calculs de longue durée. Le cas que vous devez surveiller est celui où vous avez un algorithme si pauvre, ou une mauvaise implémentation d'un algorithme, qu'il perd rapidement beaucoup de précision. Cela apparaît généralement avec toute taille raisonnable de nombre f-p. Votre suite de tests aurait dû l'exposer si c'est un vrai problème pour vous. Pour conclure: vous devez faire face à la perte de précision d'une certaine manière et il n'est pas nécessairement mauvais de brosser les détails plus fins sous le tapis.

1

Si vos cibles incluent des processeurs x86, l'utilisation du commutateur permettant à gcc d'utiliser les instructions SSE2 (au lieu de celles basées sur la pile historique) les rendra plus similaires aux autres.

Si vos cibles comprennent les processeurs PowerPC, en utilisant le commutateur qui fait gcc pas utiliser l'instruction fmadd (pour remplacer une multiplication suivie d'une addition dans le code source) rendra ces fonctionner plus comme les autres.

N'utilisez pas --fast-math: cela permet au compilateur de prendre des raccourcis, ce qui provoquera des différences entre les architectures. Gcc est plus conforme aux normes, et donc prévisible, sans cette option. Si vous incluez vos propres fonctions mathématiques (exp, sin, ...) dans votre application au lieu de vous fier à celles de la bibliothèque du système, cela ne peut que contribuer à la prévisibilité. Et enfin, même lorsque le compilateur respecte rigoureusement la norme (ici C99), il peut y avoir quelques différences, car C99 permet de calculer les résultats intermédiaires avec une précision supérieure à celle requise par le type de l'expression. Si vous vraiment voulez que le programme donne toujours les mêmes résultats, écrivez three-address code. Ou, utilisez uniquement la précision maximale disponible pour tous les calculs, qui serait double si vous pouvez éviter les instructions x86 historiques. Dans tous les cas, et non utiliser des flotteurs de faible précision dans le but d'améliorer la prévisibilité: l'effet serait le contraire, conformément à la clause ci-dessus dans la norme.

+0

De plus, les choses qui vous dérangeront sont exactement ce qui dérange les gens qui essaient d'écrire correctement des analyseurs pour C, vous devriez donc être intéressé par ce rapport: http://hal.archives-ouvertes.fr/hal- 00128124/fr /. Sauf que les auteurs des analyseurs n'ont pas le contrôle des options de compilation, mais ils travaillent dans un cadre où il suffit de prendre en compte toutes les possibilités sans en oublier aucune. –

Questions connexes