Jaký druh optimalizace provádí možnost -ffast-math
?
Viděl jsem, že čas potřebný pro jednoduchý algoritmus $ O (n ^ 2) $, který se pomocí této možnosti sníží na algoritmus $ O (n) $.
Komentáře
- Myslím, že tato otázka již má odpověď na přetečení zásobníku: stackoverflow.com/questions/7420665/…
- hlasuji ' k uzavření této otázky jako duplikátu otázky na jiném SE .
- @BillBarth: Uzavření otázky jako duplikátu obecně funguje pouze v rámci daného webu StackExchange, s výjimkou zřejmých křížových příspěvků. Diskuse a možná řešení najdete v meta.stackexchange.com/questions/172307/… na Meta StackExchange.
- @GeoffOxberry, viděl jsem to a vyzkoušel plán B.
- @BillBarth, kde si myslíte, že mohu najít komplikovanou odpověď?
Odpověď
Na tuto otázku existuje kanonická odpověď ve wiki GCC , což je pravděpodobně zachován, je to zdaleka nejautoritativnější zdroj informací pro tento typ otázek. Na druhou stranu tato otázka může nakonec zastarat. To vše je podrobněji vysvětleno na wiki s příklady. je v podstatě citát z něj, který ilustruje, jak odpovídá na tuto přesnou otázku, s drobnými komentáři:
-
-fno-signaling-nans
-
-fno-trapping-math
Standard IEEE doporučuje, aby implementace umožňovaly manipulátorům trapů zpracovávat exc možnosti jako dělení nulou a přetečení. Tento příznak předpokládá, že nedojde k žádné viditelné pasti.
-
-funsafe-math-optimizations
– Tyto optimalizace porušují zákony aritmetiky s plovoucí desetinnou čárkou a mohou je nahradit zákony běžné aritmetiky s nekonečnou přesností:Kvůli chybám zaokrouhlování asociativní zákon algebry nemusí platit pro čísla s plovoucí desetinnou čárkou, a proto výrazy jako (x + y) + z nejsou nutné rovné x + (y + z).
-
-ffinite-math-only
– speciální veličiny jakoinf
nebonan
se předpokládá, že se nikdy neobjeví, což šetří čas strávený hledáním a správným zacházením s nimi. Mělo by se například $ x – x $ vždy rovnat 0,0 $ $? -
-fno-errno-math
zakáže nastavení proměnné errno podle požadavků C89 / C99 při volání rutin matematické knihovny. Pro Fortran je toto výchozí.
-
-fcx-limited-range
způsobí, že bude při provádění komplexního dělení vynechán krok zmenšení rozsahu. To používá $ a / b = ((ar * br + ai * bi) / t) + i ((ai * br – ar * bi) / t) $ s $ t = br * br + bi * bi $ a může nefunguje dobře na libovolných rozsazích vstupů.
-
-fno-rounding-math
-
-fno-signed-zeros
Kvůli chybám zaokrouhlování nemusí asociativní zákon algebry platit pro čísla s plovoucí desetinnou čárkou, a tedy výrazy jako (x + y) + z, nejsou nutná, rovná se x + (y + z).
Přesně řečeno, důsledky posledních dvou nejsou vždy tak intuitivní, jak by si někdo myslel. Například (viz wiki), co $ – (a – a) = a – a $, je to $ + 0,0 $ nebo $ -0,0 $? Věřím, že existuje značné množství literatury o přesných důsledcích, zejména od Billa Kahana .
- Není přímo uvedeno (I nevidíte to?), ale s
-ffast-math
jsou některé běžné speciální funkce, jako je reciproční $ 1 / x $ a druhá odmocnina $ \ sqrt {x} $ nahrazeny méně přesné verze, které jsou rychlejší, ale které stále mají určité „tolerovatelné“ úrovně chyb (oproti standardním chybám 0ulp) – například zde je přesnost glibcs libm . Toto je skutečně nejčastější příčina zrychlení z-ffast-math
v kódu, který dělá hodně aritmetiky s děleními a odmocninami, téměř do té míry, že já ( osobně ) si myslí, že ostatní možnosti (-ffinite-math-only
a podobné – signalizačníNaN
s jsou pro ladění docela užitečné) způsobují také trochu z hlediska nákladů a přínosů mnoho potíží.
Viděl jsem, že čas potřebný pro jednoduché $ O (n ^ 2) $ pomocí této možnosti se algoritmus redukuje na algoritmus $ O (n) $.
Domnívám se, že je to nepravděpodobné a je možné, že jste udělali chybu ve vaší analýze.Nebezpečné optimalizace s plovoucí desetinnou čárkou mohou jednotlivé výrazy o něco levněji vyhodnotit na základě toho, že mají větší výběr optimalizací. Zrychlení by však mělo být vždy maximálně konstantní faktor. Je možné porovnat algoritmus $ O (n ^ 2) $ s $ O (n) $ pro nedostatečně velký $ n $?
Odpovědět
Algoritmus $ n ^ 2 $ lze redukovat na něco, co se chová $ O (n) $, pokud je například kompilátoru známo $ n $ a je násobkem velikosti vektoru pro vektorové instrukce (pokud existují) podporované procesorem. Pokud kompilátor toto všechno vidí, může rozbalit vnitřní smyčku a použít k provedení vektorové pokyny. To může snížit celkové provedené operace na pouhou hrstku a podstatně zlepšit výkon.
Moje četba spočívá v tom, že fast-math
takovou optimalizaci neumožňuje, ale mohla by, pokud je implicitně povolena unsafe-math-optimizations
kvůli omezením asociativity, která jsou v nich zakázána.