Che tipo di ottimizzazioni offre lopzione -ffast-math?

Ho visto che tempo impiegato per un semplice algoritmo $ O (n ^ 2) $ che viene ridotto a quello di un algoritmo $ O (n) $ utilizzando lopzione.

Commenti

  • Penso che questa domanda abbia già una risposta su Stack Overflow: stackoverflow.com/questions/7420665/…
  • Voto ' per chiudere questa domanda come duplicato di una domanda su un SE diverso .
  • @BillBarth: la chiusura di una domanda come duplicata generalmente funziona solo allinterno di un determinato sito StackExchange, ad eccezione degli ovvi messaggi incrociati. Vedi meta.stackexchange.com/questions/172307/… su Meta StackExchange per discussioni e possibili soluzioni.
  • @GeoffOxberry, lho visto e ho provato un piano B.
  • @BillBarth dove pensi che avrei potuto trovare una risposta elaborata?

Risposta

Cè una risposta canonica a questa domanda nel wiki di GCC , che è presumibilmente mantenuta, è di gran lunga la fonte di informazione più autorevole per questo tipo di domanda. Questa domanda, daltra parte, potrebbe eventualmente non essere aggiornata. Tutto questo è spiegato più dettagliatamente nel wiki, con esempi. Quanto segue è essenzialmente una citazione per illustrare come risponde a questa domanda esatta, con commenti minori:

  • -fno-signaling-nans
  • -fno-trapping-math

    Lo standard IEEE raccomanda che le implementazioni consentano ai gestori di trap di gestire exc eptions come dividi per zero e overflow. Questo flag presume che non si verifichi alcun trap visibile alluso.

  • -funsafe-math-optimizations – Queste ottimizzazioni infrangono le leggi dellaritmetica in virgola mobile e possono sostituirle con le leggi dellaritmetica ordinaria a precisione infinita:

    A causa di errori di arrotondamento lassociativo la legge dellalgebra non è necessaria per i numeri in virgola mobile e quindi espressioni come (x + y) + z non sono necessarie uguali a x + (y + z).

  • -ffinite-math-only – Quantità speciali come inf o nan non compaia mai, in questo modo si risparmia il tempo speso a cercarli e gestirli in modo appropriato. Ad esempio, $ x – x $ dovrebbe sempre essere uguale a $ 0,0 $?

  • -fno-errno-math

    disabilita limpostazione della variabile errno come richiesto da C89 / C99 sulla chiamata delle routine della libreria matematica. Per Fortran questa è limpostazione predefinita.

  • -fcx-limited-range

    fa in modo che il passo di riduzione dellintervallo venga omesso quando si esegue una divisione complessa. Questo usa $ a / b = ((ar * br + ai * bi) / t) + i ((ai * br – ar * bi) / t) $ con $ t = br * br + bi * bi $ e potrebbe non funziona bene su intervalli arbitrari degli input.

  • -fno-rounding-math

  • -fno-signed-zeros

    A causa di errori di arrotondamento, la legge associativa dellalgebra non è necessaria per numeri in virgola mobile e quindi espressioni come (x + y) + z non sono necessariamente uguali a x + (y + z).

A rigor di termini, le implicazioni degli ultimi due non sono sempre così intuitive come si potrebbe pensare. Ad esempio (vedi wiki), che dire di $ – (a – a) = a – a $, è $ + 0,0 $ o $ -0,0 $? Credo che ci sia una discreta quantità di letteratura sulle esatte implicazioni, in particolare di Bill Kahan .

  • Non menzionato direttamente (I non lo vedi?), ma con -ffast-math, alcune funzioni speciali comuni come il reciproco $ 1 / x $ e la radice quadrata $ \ sqrt {x} $ vengono sostituite con meno versioni precise che sono più veloci, ma che hanno ancora alcuni livelli di errore “tollerabili” (rispetto allerrore 0ulp richiesto dallo standard) – qui, ad esempio, è la precisione solitamente fornita da libm di glibc “s . In effetti, questa è la causa più comune di accelerazione da -ffast-math, in un codice che fa molta aritmetica con divisioni e radici quadrate, quasi al punto che io ( personalmente ) penso che le altre sotto-opzioni (-ffinite-math-only e simili in particolare – la segnalazione di NaN siano abbastanza utili per il debug) perché anche un po molto fastidioso in termini di costi / benefici.

Ho visto che il tempo impiegato per un semplice $ O (n ^ 2) $ lalgoritmo viene ridotto a quello di un algoritmo $ O (n) $ utilizzando lopzione.

Credo che questo sia improbabile ed è possibile che tu abbia commesso un errore nella tua analisi.Le ottimizzazioni in virgola mobile non sicure potrebbero rendere le singole espressioni un po più economiche da valutare in virtù della disponibilità di una più ampia scelta di ottimizzazioni. Ma laccelerazione dovrebbe essere sempre al massimo un fattore costante. È possibile che tu abbia confrontato un algoritmo $ O (n ^ 2) $ con un $ O (n) $ per $ n $ non sufficientemente grandi?

Risposta

Un algoritmo $ n ^ 2 $ può essere ridotto a qualcosa che si comporta $ O (n) $ se, ad esempio, se $ n $ è noto al compilatore ed è un multiplo della dimensione del vettore per le istruzioni vettoriali (se presenti) supportate dal processore. Se il compilatore può vedere tutto questo, può srotolare un ciclo interno e utilizzare istruzioni vettoriali per eseguire il lavoro. Ciò può ridurre le operazioni complessive eseguite a una manciata e migliorare sostanzialmente le prestazioni.

La mia lettura è che fast-math non abilita tale ottimizzazione, ma potrebbe farlo se sono implicitamente abilitate dal unsafe-math-optimizations a causa di limitazioni di associatività che sono disabilitate al suo interno.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *