Vadí to třeba u Kahanova sčítání (https://en.wikipedia.org/wiki/Kahan_summation_algorithm). Tam se podobným výpočtem (který by na nezaokrouhlených reálných číslech dal samozřejmě nulu) sleduje a koriguje nasbíraná chyba.
Přepsat ty vzorečky podle normálních matematických pravidel ten výpočet naprosto rozbije.
Ako casto ale realne potrebujes nieco taketo? Ak to potrebujes casto, asi to nebude jediny tym vypoctu (scitanie N cisiel) ale budu to zrejme rozne dalsie matematicke operacie. Tak tam predpokladam ze pouzijes nejaku matematicku kniznicu ktora to ma implementovane a v pripade potreby je aj buildovana sposobom ktory dodrzi matematiku vo forme aka bola zamyslana v kode.
Pretoze inak mi to pride na bezne "kazdodenne vypocty" ako kanon na vrabce.
3. 5. 2024, 14:35 editováno autorem komentáře
> Ako casto ale realne potrebujes nieco taketo?
To silně záleží na oboru. Ten součet byl jen jen příklad.
> pouzijes nejaku matematicku kniznicu
Problém je, že nastavení floatového prostředí je globální stav. Není úplně levné ho přepínat. A není moc zvykem na hranicích knihoven ten floatový stav pořád ukládat a obnovovat.
V odkazované diskuzi zaznělo, že to ffast-math je nebezpečné i kvůli těmhle nelokálním efektům, které rozbíjejí volané knihovny. https://trofi.github.io/posts/302-Ofast-and-ffast-math-non-local-effects.html
> "kazdodenne vypocty"
Právě že ty každodenní výpočty nejsou obvykle moc FP heavy, takže nějaké ffast-math není rozumný default.
Ten odkaz je výborná ilustrace. Náhodou jsem ten libsodium "incident" řešil - knihovna která s floaty snad ani nic nedělá "omylem" použila -Ofast a pak to rozbíjelo i cizí kód okolo.
3. 5. 2024, 20:25 editováno autorem komentáře
Možná by to chtělo nastudovat floating point?
Třeba `b - b` může být nula, ale může to být taky NaN. Takže za normálních okolností compiler nesmí ten výraz optimalizovat.
Druhý příklad - `a + 0` -> pokud `a` je -0.0, tak výsledek bude 0, takže celkem regulérní způsob jak se zbavit -0 třeba před uložením binární hodnoty...
Existuje hodně případů, kdy je FP kód napsaný tak, že si třeba počítá chybu a tu koriguje. Takto dokáže přemýšlet možná tak 5% lidí, ale pořád je to důležité... No a pak přijde někdo, kdo přidá do flagů -ffast-math, a strašně se pak diví, že se rozbije něco, čemu nerozumí...
Takove zrudnosti ale nepatri do vyssiho jazyka, ktery by mel delat logickou optimalizaci a eliminaci mrtveho kodu, coz +b-b jiste je, stejne jako aby se provedl constant folding.
Pokud nekdo vyuziva specifickeho chovani FPU a IEEE datovych typu, tak at si to napise v asm, nebo pouzia k tomu urcene knihovny, kde by jste z nicnerikajiciho b=a+0 migrovali na b=eliminate_minus_zero(a);
Neni nic horsiho, nez kdyz nekdo pise "optimalizovany zdrojak" a pak ten, co to cte, musi premyslet nad implementacnimi detaily ve vztahu k urcite architekture (jakkoliv ieee754 je widespread, tak tyhle triky zna malokdo).
Tady jde o korektnost. Není možnost jak napsat s -ffast-math ten kahan algoritmus nebo třeba double-double, atd...
Každý, kdo se rozhodne použít float využívá chování IEEE - je to jasně definované a není to žádná megie nebo vytváření "optimalizovaného zdrojáku".
Co se týče přesnosti tak i zdánlivě triviální problém jako třeba řešení kvadratické rovnice se dá napsat "podle knížky" a nebo s využitím znalostí toho jak funguje float, hezký příklad třeba tady:
https://stackoverflow.com/questions/4503849/quadratic-equation-in-ada/4504415#4504415
Jedním z problémů Fastmath je to, že kvůli němu nejsou výsledky výpočtů deterministické.
Program, který používá floaty, sice nespočítá zcela přesný výsledek, ale alespoň pokaždé spočítá výsledek stejný.
Například v případě multiplayerové hry to znamená, že se hráči a server mohou vždy shodnout na tom, kde budou objekty za sekundu, pokud se shodnou na tom, kde jsou teď.
(I když počítačové hry právě mnohdy fastmath používají a musí tohle řešit jinak...)