2013-07-12 5 views
10

Poiché l'opzione gcc-ffast-math disabilita efficacemente NaN e -/+inf, sto cercando forse la prossima opzione migliore per rappresentare NaN nel mio codice di matematica prestazioni critiche. Idealmente il valore sentinella se attivato (add, mul, div, sub, ecc.) Restituirebbe il valore sentinella come farebbe NaN ma dubito che ciò sarebbe possibile poiché penso che lo NaN sia l'unico valore che lo compie. -0.0 potrebbe non essere una buona misura, come è anche disattivato nel -ffast-math e potrebbe prevenire alcune ottimizzazioni come (x+0.0), ecc ..Un buon rapporto qualità sentinella per il doppio, se preferisce utilizzare -ffast-math

Forse la mia domanda dovrebbe piuttosto essere, c'è qualche modo per utilizzare NaN o qualche altro mentre "speciale doppio" essere in grado di abilitare molte ottimizzazioni matematiche senza abbattere?

Il sistema è Linux/x64, gcc 4.8.1.

+4

Questa discussione potrebbe essere utile [Mingw32 std :: isnan con -ffast-math] (http://stackoverflow.com/questions/7263404/mingw32-stdisnan-with-ffast-math) –

+0

@ShafikYaghmour Grazie, quella discussione è utile – stgtscc

+2

Esiste anche l'opzione di usare '-fno-finite-math-only -ftrapping-math' http://lua-users.org/lists/lua-l/2009-04/msg00091.html –

risposta

4

Se si sta cercando un valore che sarebbe propagato mediante operazioni aritmetiche, NaN è ancora disponibile con l'opzione -ffast-math. Il problema sta da qualche altra parte. Con -ffast-math alcune operazioni possono essere rimosse dal calcolo a causa dell'ottimizzazione, e quindi non c'è modo di garantire NaN o qualsiasi altro valore si propagherebbe.

Ad esempio, il seguente, con -ffast-math set, causerà difficile scrivere 0.0 in n e non v'è alcun valore speciale per n che proteggerebbe da esso.

float n = NAN; 
n *= 0.0; 

Una cosa si può fare, è quello di utilizzare -fno-finite-math-only -ftrapping-math con -ffast-math come ha detto Shafik Yaghmour. E l'altro è, se ci sono solo pochi punti in cui ci si aspetta un valore negativo, è possibile verificarlo da solo mettendo i test esattamente in quei punti.

L'ultima opzione che posso pensare, se davvero hai bisogno dell'ottimizzazione, è iniettare manualmente i valori NaN (e forse inf) nel calcolo e controllare per quanto tempo viene propagato. Quindi, in quei luoghi in cui si interrompe la propagazione, verificare l'occorrenza di NaN (inf). - Questo è un metodo non sicuro, in quanto non ne sono sicuro al cento per cento, è possibile che lo -ffast-math implichi il flusso condizionale delle operazioni. Se è possibile, c'è una possibilità significativa, questa soluzione non sarà valida. Quindi è rischioso e se scelto richiede test molto pesanti che coprano tutti i rami del calcolo.

Normalmente sarei piuttosto contrario all'ultima soluzione, ma in realtà c'è una possibilità, NaN (inf) i valori verranno propagati attraverso l'intero calcolo o quasi interi, in modo da poter fornire le prestazioni che stai cercando. Quindi potresti voler correre il rischio.


Controllo della NaN con -ffast-math si può fare, come diceva Shafik Yaghmour, con

inline int isnan(float f) 
{ 
    union { float f; uint32_t x; } u = { f }; 
    return (u.x << 1) > 0xff000000u; 
} 

e per double con

inline int isnan(double d) 
{ 
    union { double d; uint64_t x; } u = { d }; 
    return (u.x << 1) > 0xff70000000000000ull; 
} 

Controllo per inf sarebbe

inline int isinf(float f) 
{ 
    union { float f; uint32_t x; } u = { f }; 
    return (u.x << 1) == 0xff000000u; 
} 

inline int isinf(double d) 
{ 
    union { double d; uint64_t x; } u = { d }; 
    return (u.x << 1) == 0xff70000000000000ull; 
} 

È inoltre possibile unire isnan e isinf.

Problemi correlati