Stabilité numérique d'un code

a marqué ce sujet comme résolu.

Bonjour à tous,

J’ai un code fortran, assez long et assez complexe (sans être fou non plus), et j’ai un problème de stabilité.

On a remarqué que ces deux lignes ne donnent pas les même résultats finaux.

variable1=variable2/3.0_dp
variable1=variable2*(1.0_dp/3.0_dp)

variable1 et variable 2 sont aussi en double précision. En comparant, il y a parfois une différence dans le dernier chiffre, que j’imagine due à la manière dont l’ordinateur fait les calculs. On parle donc du 16ème chiffre significatif.

variable 1 est ensuite réinjecté dans une autre fonction pour faire des calculs qui impactent tout le reste du code. Les résultats finaux varient au 3ème ou 4ème chiffre significatif. Je me suis donc dit qu’il y avait un problème de stabilité quelque part, des soustractions qui rendent cette différence plus importante, ou que sais-je. Après plus ou moins un jour à chercher, sans succès, j’ai simplement essayé

Cas 1

variable1=variable2/3.0_dp
variable1=variable1*1.0000000000001_dp

Cas 2

variable1=variable2/3.0_dp
variable1=variable1*1.01_dp

Dans les deux cas, les résultats finaux changent mais moins qu’en rajoutant des parenthèses autour de la division par 3. Du coup, je ne comprends pas. Il semblerait qu’il n’y ait pas de super-sensibilité de l’algo (ou peut-être que si quand même), mais il y a quand même quelque chose de très étrange. Toute idée est la bienvenue !

Merci !

Salut,

Les questions de stabilité en calcul flottant sont loin d’être triviales (principalement en raison du caractère discret des quantité manipulées). Sans tes équations, il va être difficile de t’aider bien plus.

+0 -0

Mes excuses.

Le compilateur est ifort (intel_XE_2015, composer_xe_2015.2.164)

Les options sont -O -assume underscore -names lowercase -u -align -fpe0 -assume protect_parens -prec_sqrt -fp-model source -traceback -module ../modules -c

Par contre, je n’ai contractuellement pas le droit de poster mes équations. Je suis bien conscient que ça complique les choses (a minima). Mais si ce changement sur le 16ème nombre significatif est si important (d’où que ça vienne), pourquoi un changement sur le 3ème a moins d’effet ?

Mais si ce changement sur le 16ème nombre significatif est si important (d’où que ça vienne), pourquoi un changement sur le 3ème a moins d’effet ?

Justement parce que tu manipules des données discrètes. L’erreur propagée n’est pas nécessairement proportionnelle à l’erreur de départ.

+1 -0

Je reformule, parce que ce n’était pas évident à la première lecture.

Tu es en train de dire qu’en remplaçant variable1=variable2/3.0_dp par variable1=variable2*(1.0_dp/3.0_dp), et en lançant ton algo, tu obtiens un écart. Normal, pourquoi pas.

Puis en refaisant le test, mais en remplaçant variable1=variable2/3.0_dp par les 2 instructions variable1=variable2/3.0_dp puis variable1=variable2*1.01_dp, tu obtiens toujours un écart, mais moindre que dans le premier scénario.

Pourquoi pas, ça peut arriver. Mais c’est surprenant.

Si dans le fameux algo, tu utilises des fonctions non continues (partie-entière par exemple), alors ok, tu peux obtenir des trucs très surprenant.

Si tu as des nombres qui deviennent négatifs dans un scénario, et positifs dans l’autre, alors là aussi, ça peut aller très vite, et donner les résultats que tu décris dans certains cas.

Si dans l’algo, tu passes par des tests comme si a<b alors , tu peux aussi avoir ce phénomène, si dans un scénario, on se retrouve avec a<b, et dans l’autre scénario, on ne passe pas par les mêmes instructions.

Je ne dis que des évidences, mais as-tu vérifié ces évidences. Est-ce que tu es dans un de ces cas ?

Si dans le fameux algo, tu utilises des fonctions non continues […]

Encore une fois, on travaille avec des flottants, les fonctions continues n’existent pas. Plus concrètement, ça veut dire que les trajectoires des nombres flottants soumis à des opérations pourtant continues sur R\mathbb R peuvent (et vont, loi de Murphy oblige) se croiser. Avoir une erreur qui ne se comporte pas de façon monotone avec l’erreur de départ n’a donc absolument rien de surprenant. Et ce même si le code fait des choses en apparence très simples (bonjour les additions et soustractions). Et de fait, la précision d’un calcul numérique donné n’est pas la précision machine.

EDIT : une lecture intéressante sur le sujet.

+1 -0

Les options sont -O -assume underscore -names lowercase -u -align -fpe0 -assume protect_parens -prec_sqrt -fp-model source -traceback -module ../modules -c

Rockaround

Ce qui m’intéressait était l’option -fp-model (ou ton niveau d’optimisation si il n’était pas défini explicitent).

-fp-model <keyword> Controls the semantics of floating-point calcula� tions. The following are -fp-model options:

      � -fp-model precise

    Enables  value-safe  optimizations  on  floating-
    point data and  rounds  intermediate  results  to
    source-defined precision.  Disables optimizations
    that can change the result of floating-point cal�
    culations, which is required for strict ANSI con�
    formance. These semantics ensure the accuracy  of
    floating-point  computations,  but  they may slow
    performance.

    Floating-point exception semantics  are  disabled
    by default.

    This option is equivalent to -fp-model source.

      � -fp-model fast[=1|2]

    Enables more aggressive optimizations when imple�
    menting floating-point calculations. These  opti�
    mizations increase speed, but may alter the accu�
    racy of floating-point computations.

    Specifying fast is the same as specifying fast=1.
    fast=2  may  produce  faster  and  less  accurate
    results.

    Floating-point exception semantics  are  disabled
    by default and they cannot be enabled.

      � -fp-model strict

    Enables   precise   and   except.   This  is  the
    strictest floating-point model.

      � -fp-model source

    Enables  value-safe  optimizations  on  floating-
    point  data  and  rounds  intermediate results to
    source-defined precision. This option is  equiva�
    lent to -fp-model precise.

doc intel

J’ai déjà eu des différences entre debug et release à cause d’un fp-model fast en release mais visiblement ton option est équivalente à fp-model precise. Est ce que tu as toujours les différences avec un fp-model strict ?

+1 -0

J’ai déjà eu des différences entre debug et release à cause d’un fp-model fast en release mais visiblement ton option est équivalente à fp-model precise. Est ce que tu as toujours les différences avec un fp-model strict ?

Ça semble avoir réglé le problème, mais j’ai peur que ce ne soit qu’en surface. La partie du code qui rendait ces détails important est toujours là.

une lecture intéressante sur le sujet.

Merci, pour le lien et les commentaires dans le sujet. C’est vrai que c’est un sujet complexe, mais qui mérite que ceux qui prétendent faire des calculs assez précis se penchent dessus. Après, maîtriser tout ça complètement, c’est un boulot entier en soit.

Ça semble avoir réglé le problème, mais j’ai peur que ce ne soit qu’en surface. La partie du code qui rendait ces détails important est toujours là.

Rockaround

La page de adri1 te donnera des pistes, j’ai vu que ça parle de Kahan entre autre. Il y a aussi un article de @kfc sur la méthode CESTAC qui peut t’intéresser.

+1 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte