Le Livre d'Argent

[Nouvel article] Comment j'ai rejoint la communauté du bug 323

Attachez vos ceintures pour l'histoire d'un bug incompréhensible dont l'origine se trouve finalement directement dans une unité de calcul du processeur…

https://studios.ptilouk.net/superflu-riteurnz/blog/2023-08-11_bug323.html

@gee Quelle persévérance 👏.

@gee Ah ! Mais évidemment, tu fais un test d'égalité sur des doubles ! Faut jamais faire ça ! Le problème vient de là !

@gee Ah ça fait plaisir, comme je voyais que tu parlais de bug de compile j'ai pensé aussi à `volatile` (et non `votalile`, typo dans ton billet — encore un coup du lobby pro-Martine Aubry). Dans le mille ; ça a une bonne tendance à inhiber toutes les optimisations des compilateurs.

@bnjbvr ah merci pour la typo, je corrige !

@gee Par contre, un peu surpris que gcc utilise encore le x87 🥴 j'aurais cru qu'on utilisait SSE2 depuis un moment pour toutes les maths flottantes (même en SISD). Peut-être qu'un petit `-msse2` règlerait aussi ton problème ?

@gee Joli ! Bravo d’avoir été jusqu’au bout, on découvre en effet des pépites.

Ceci dit je suis surpris que 1.0/2.0 soit pas égal à 0.5 (il me semble que justement c’est un nombre exact en flottant). Le bon exemple serait 1.0/5.0 qui n’est pas égal à 0.2 plutôt (sauf que c’est pas complètement vrai non plus, si tu écris 1.0/5.0 == 0.2 ça retourne vrai parce que le calcul renvoie le même flottant…).

@amic tu as raison, mais en fait ça marche aussi pour 1./5. et 0.2 (et pour plein d'autres trucs, c'est plus robuste que ce que je croyais). Je vais essayer de trouver un meilleur exemple.

@amic bon, je trouve pas d'exemple simple, faut forcément faire des calculs un peu compliqués pour que l'erreur soit suffisamment importante pour faire merdouiller un calcul exact en réels.

Du coup j'ai juste un peu changé la formulation (« pas garanti d'être égal à »), ce qui n'est pas faux 😅

@gee Très chouette article.

J'ai notamment beaucoup aimé, parce qu'en lisant l'évolution de ta position sur l'hypothèse que ça puisse être un bug du compilateur en fonction de l'avancée de la vérification des autres hypothèses, j'ai pensé très fort « principe de parcimonie » (ou rasoir d'Ockham/d'Occam), et que tu conclues par juste la satisfaction de comprendre ce qui se passe.

La beauté de la démarche scientifique appliquée au débuggage.
replies
0
announces
0
likes
2

@gee Question con.

Du coup je suis curieux, est-ce que le code suivant fonctionne ?

if a < b {
return deviation(a) <= deviation(b);
} else {
return deviation(a) < deviation(b);
}

@gee (en d'autres termes, est-ce que dans ce cas les deux valeurs sont stockées en précision ultime dans les registres et du coup ça marche ?)

@karl alors si je ne m'abuse, il faudrait plutôt écrire ça :

if (a == b) {
return deviation(a) < deviation(b);
} else {
return a < b;
}

Et oui, ça a l'air de marcher, probablement pour la raison que tu donnes 🙂

@gee Hum, il manque un morceau, non ? Les déviations respectives de a et b doivent être évaluées dans tous les cas.

(et j'ai fait la table de vérité de mon snippet, c'est exactement la même que l'original. La clause da==db est cachée dans le caractère strict ou non des comparaisons et dans le if ... else)

@karl oui j'ai fait n'imp effectivement 😅

@gee
Le code original peut être lu comme :

  • quand a < b
    • soit da==db et return true
    • soit da!=db et return da < db
    • --> return da <= db
  • quand !(a < b)
    • soit da==db et return false
    • soit da!=db et return da < db
    • --> return da < db