7
votes

Différent comportement d'arrondi de maths entre Linux, Mac OS X et Windows

salut,

J'ai développé un code mixte C / C ++, avec des calculs numériques intensives. Lors de la compilation dans Linux et Mac OS X, j'ai des résultats très similaires après la fin de la simulation. Sous Windows, le programme compile également, mais je reçois des résultats très différents et parfois, le programme ne semble pas fonctionner.

J'ai utilisé des compilateurs GNU dans tous les systèmes. Certains amis me recommandent d'ajouter des maths de fraude et la version Windows semble fonctionner plus stable, mais Linux et OS X, leurs résultats, ne changent pas du tout.

Pourriez-vous recommander une autre option pour obtenir plus de concordance entre les versions Win et Linux / OSX?

merci

p.d. J'ai aussi essayé -O0 (aucune optimisation) et spécifié -M32


1 commentaires

Linux et OS X utilisent les deux GCC, alors je m'attendrais à ce que les mêmes résultats - fournis tous deux ont couru sur la même architecture de processeur. Avez-vous vraiment eu des résultats «similaires»? Si tel est le cas, certains aléateurs semblent être injectés dans vos calculs. Toute variables non initialisées ?!


4 Réponses :


9
votes

Il existe quatre types d'arrondissement différents pour les nombres à virgule flottante: rond vers zéro, arrondi, arrondir et rond au nombre le plus proche. En fonction du système de compilateur / d'exploitation, la valeur par défaut peut être différente sur différents systèmes. Pour changer de manière programmée sur la méthode d'arrondi, voir festartound . Il est spécifié par C99 Standard, mais peut être disponible pour vous.

Vous pouvez également essayer l'option -ffloat-store GCC. Cela essaiera d'empêcher GCC d'utiliser des valeurs de point flottant 80 bits dans des registres.

En outre, si vos résultats changent en fonction de la méthode d'arrondi et que les différences sont significatives, cela signifie que vos calculs peuvent ne pas être stables. Veuillez envisager de faire une analyse d'intervalle ou d'utiliser une autre méthode pour trouver le problème. Pour plus d'informations, reportez-vous à la section Comment les futilations sont des évaluations incluses du relancement dans le calcul de point flottant? (pdf) et Les pièges de vérification des calculs à virgule flottante (Lien ACM , mais vous pouvez obtenir un PDF à partir de nombreux endroits si cela ne fonctionne pas pour vous).


1 commentaires

+1 Pour la stabilité numérique: si les résultats varient sensiblement sur la base de l'arrondi, il y a quelque chose qui ne va pas avec les calculs. Et juste pour exclure l'évidence: vous avez utilisé «double» et non seulement «flotter» pour vos variables ?!



10
votes

Je ne peux pas parler de la mise en œuvre sous Windows, mais les puces Intel contiennent des registres de points flottants 80 bits et peuvent donner une précision plus précise que celle spécifiée dans la norme Point flottante IEEE-754. Vous pouvez essayer d'appeler cette routine dans le principal () de votre application (sur les plates-formes de puce Intel): xxx

i pense ceci est distinct des modes d'arrondi discutés par @Alok.


2 commentaires

+1 pour mentionner les registres 80 bits. Je ne savais pas sur _fpu _ * .


Et c'est sur x87, qui ne devrait plus être utilisé. SSE Math est beaucoup plus rapide



1
votes

Outre les paramètres d'arrondi d'exécution que les personnes mentionnées, vous pouvez contrôler les paramètres de compilateur Visual Studio dans Propriétés> C ++> Génération de code> Modèle de point flottant. J'ai vu des cas où le réglage de celui-ci sur "rapide" peut causer un mauvais comportement numérique (par exemple, des méthodes itératives ne convergent pas).

Les paramètres sont expliqués ici: http://msdn.microsoft.com/fr- US / Bibliothèque / E7S85FFB% 28vs.80% 29.aspx


1 commentaires

Cela va au même problème cependant. Le réglage du modèle de point flottant VC ++ peut être défini pour forcer les représentations internes à 80 bits à arrondir à leurs équivalents de 64 bits à des temps définis bien définis, et cela devrait rendre les résultats compatibles avec d'autres implémentations qui utilisent 64 bits tout le chemin par.



0
votes

Les normes IEEE et C / C ++ laissent certains aspects de la mathématique à virgule flottante non spécifiée. Oui, le résultat précis de l'ajout aux flotteurs est déterminé, mais tout calcul plus compliqué n'est pas. Par exemple, si vous ajoutez trois flotteurs, le compilateur peut effectuer l'évaluation à la précision du flotteur, double précision ou plus. De même, si vous ajoutez trois doubles, le compilateur peut effectuer l'évaluation à la double précision ou supérieure.

VC ++ par défaut pour définir la précision X87 FPU à doubler. Je crois que GCC le laisse à une précision de 80 bits. Ni est clairement meilleur, mais ils peuvent facilement donner des résultats différents, surtout s'il y a une instabilité dans vos calculs. En particulier, «minuscule + grand - grand» peut donner des résultats très différents si vous avez des bits supplémentaires de précision (ou si l'ordre d'évaluation change). Les implications de la précision intermédiaire variable sont discutées ici:

http://randomascii.wordpress.com/2012 / 03/12 / intermédiaire-flottant-point-point-précision /

Les défis du point flottant déterministe sont discutés ici:

http://randomascii.wordpress.com/2013/07 / 16 / Déterminisme à point flottant /

La mathématique du point flottant est délicate. Vous devez savoir quand vos calculs divergent et examinent le code généré pour comprendre pourquoi. Seulement alors pouvez-vous décider quelles actions à prendre.


0 commentaires