11
votes

Existe-t-il un (Linux) G ++ équivalent à la / FP: précision et / FP: drapeaux rapides utilisés dans Visual Studio?

arrière-plan:

Il y a de nombreuses années, j'ai hérité d'une base de code qui utilisait le drapeau Visual Studio (VC ++) / FP: Fast 'pour produire un code plus rapide dans une bibliothèque de calcul particulière. Malheureusement, '/ FP: Fast' a produit des résultats légèrement différents pour la même bibliothèque sous un autre compilateur (Borland C ++). Comme nous avions besoin de produire exactement les mêmes résultats, je suis passé à «/ FP: précis», qui a bien fonctionné, et tout a été pêchy depuis. Cependant, maintenant je compile la même bibliothèque avec G ++ sur Ubuntu Linux 10.04 et je vois un comportement similaire, et je me demande si cela pourrait avoir une cause première similaire. Les résultats numériques de My G ++ Build sont légèrement différents des résultats numériques de My VC ++ Build. Cela m'amène à ma question:

question:

Le G ++ a-t-il des paramètres équivalents ou similaires aux options 'FP: Fast' et 'FP: précise' dans VC ++? (Et que sont-ils? Je veux activer l'équivalent "FP: précis")

Plus d'informations Verbose:

Je compile à l'aide de "make", qui appelle g ++. Autant que je puisse dire (les fichiers de fabrication sont un peu cryptiques et n'étaient pas écrits par moi) Les seuls paramètres ajoutés à l'appel G ++ sont les "Normal" (Inclure les dossiers et les fichiers à compiler) et -FICP ( Je ne suis pas sûr de ce que ce commutateur fait, je ne le vois pas sur la page "Man").

Les seuls paramètres pertinents de «Man G ++» semblent être destinés à tourner les options d'optimisation. (E.G. -Funsafe-Math-Optimisations). Cependant, je ne pense pas que je renseigne quoi que ce soit, je veux juste transformer l'optimisation pertinente.

J'ai essayé la sortie et les constructions de débogage, VC ++ donne les mêmes résultats pour la libération et le débogage, et g ++ donne les mêmes résultats pour la libération et le débogage, mais je ne peux pas obtenir la version g ++ pour donner les mêmes résultats que le VC ++ version.


4 commentaires

J'ai trouvé le sens de -ffic après un peu plus de googling: -Pic si pris en charge pour la machine cible, le code indépendant de la position émetteur, adapté à une liaison dynamique, même si (3, n) des branches nécessitent de grands déplacements.


Cela peut prendre du temps, mais vaut bien l'effort: pouvez-vous essayer de poupiller la première instruction (ou au moins une ligne de code) lorsque certains calculs se divergent entre MSVC et GCC?


Oui, je travaille sur votre suggestion. Malheureusement, je suis un peu sur un N00B Linux, alors ça me prend du temps pour tout obtenir ensemble!


Bonjour, avez-vous déjà résolu ce problème?


5 Réponses :


5
votes

Je ne pense pas qu'il y ait un équivalent exact. Vous pouvez essayer -mfpmath = sse au lieu du -mfpmath = 387 pour voir si cela aide.


1 commentaires

Lequel dois-je utiliser -mfpmath = sse ou -ffloat-store les deux résout mon problème.



18
votes

du Manuel de la GCC :

-ffloat-store Ne stockez pas les variables de points flottantes dans des registres et inhiber d'autres options pouvant changer si une valeur de point flottante est extraite d'un registre ou d'une mémoire.

Cette option empêche une précision excessive indésirable sur des machines telles que la 68000 où les registres flottants (du 68881) gardent plus de précision qu'un double est censé avoir. De même pour l'architecture X86. Pour la plupart des programmes, la précision excédentaire ne fonctionne que bien, mais quelques programmes reposent sur la définition précise du point flottant IEEE. Utilisez -ffloat-Store pour ces programmes, après les modifier pour stocker tous les calculs intermédiaires pertinents en variables.

Pour développer un peu, la plupart de ces divergences proviennent de l'utilisation des registres de points flottants X86 80 bits pour calculs (contre les 64 bits utilisés pour stocker des valeurs double ). Si les résultats intermédiaires sont conservés dans les registres sans écrire en mémoire, vous obtenez efficacement 16 bits de précision supplémentaire dans vos calculs, ce qui les rend plus précis, mais éventuellement divergent des résultats générés par des valeurs intermédiaires en mémoire (ou des calculs sur Les architectures qui n'ont que 64 bits de registres PF).

Ces drapeaux (à la fois dans GCC et MSVC) forcent généralement la troncature de chaque résultat intermédiaire à 64 bits, rendant ainsi des calculs insensibles aux aléas de la génération de code et des différences d'optimisation et de plate-forme. Cette consistance vient généralement avec un léger coût d'exécution en plus du coût en termes de précision / de précision.


2 commentaires

Cela ne s'est pas révélé être le problème, mais merci pour votre réponse bien pensée. Votre lien était très utile


Désolé de l'entendre. Peut-être que cela a quelque chose à voir avec des modes d'arrondi? Vous pouvez examiner l'assemblage généré pour un programme minimal pour lequel vous obtenez des résultats divergents et voir si le FPU est configuré différemment dans MSVC vs. GCC. Ensuite, vous pouvez essayer de cartographier ces paramètres FPU sur différents drapeaux de compilateur jusqu'à ce que vous trouviez le drapeau magique.



10
votes

La précision du registre excédentaire est un problème uniquement sur les registres FPU, que les compilateurs (avec les bons commutateurs d'activation) ont tendance à éviter de toute façon. Lorsque des calculs de points flottants sont effectués dans des registres SSE, la précision du registre est égale à la mémoire une.

dans mon expérience la plupart des / PF: Impact rapide (et divergence potentielle) provient du compilateur qui prenait la liberté pour effectuer des transformations algébraïques. Cela peut être aussi simple que le changement d'ordre d'été: p>

( a + b ) + c --> a + ( b + c)


3 commentaires

Merci pour l'idée! «Non-insécurité-math-optimisations» est définie par défaut, mais j'essayais ce que vous avez suggéré et défini explicitement, mais cela n'a pas fait de différence.


J'ai "accepté" cette réponse pour l'instant, je pense que cela répond à ma question même si malheureusement pour moi, cela n'a pas résolu mon problème. :(


Désolé d'entendre ça, espérons que quelqu'un d'autre pourrait avoir une meilleure idée.



1
votes

Ceci n'est certainement pas lié aux drapeaux d'optimisation, en supposant que "débogage" vous voulez dire "avec des optimisations éteintes". Si G ++ donne les mêmes résultats dans le débogage que dans la libération, cela signifie que ce n'est pas une question liée à l'optimisation. Les constructions de débogage doivent toujours stocker chaque résultat intermédiaire en mémoire, garantissant ainsi les mêmes résultats que / FP: précise pour MSVC.

Cela signifie probablement qu'il y a (a) un bogue de compilateur dans l'un des compilateurs, ou plus probablement (b) un bogue de la bibliothèque de mathématiques. Je percerais dans des fonctions individuelles dans votre calcul et je me limite lorsque la divergence réside. Vous trouverez probablement une solution de contournement à ce moment-là, et si vous trouvez un bogue, je suis sûr que l'équipe concernée aimerait en entendre parler.


1 commentaires

Merci Drew, je pense que vous avez raison, et je vais faire comme vous le suggérez



0
votes

-mpc32 ou -mpc64?

Mais vous devrez peut-être recompiler C et des bibliothèques mathématiques avec le commutateur pour voir la différence ... Ceci peut s'appliquer aux options d'autres suggérées également.


0 commentaires