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 jako inf nebo nan 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.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *