2013-07-12 22 views
10

Od opcją gcc-ffast-math skutecznie uniemożliwia NaN i -/+inf, szukam może następnym najlepszym rozwiązaniem dla reprezentujących NaN w moim wykonaniu krytyczne kodu matematyki. Najlepiej jeśli wartość wartownika, jeśli operowano na (dodać, mul, div, sub, itp.) Dałaby wartość wartownika jako NaN, ale wątpię, aby było to możliwe, ponieważ uważam, że jedyną wartością, która to zapewnia jest NaN. -0.0 może nie być dobrym rozwiązaniem, ponieważ jest również wyłączona w -ffast-math i może zapobiec pewne optymalizacje jak (x+0.0), etc ..Dobra jakość Sentinel dla podwójnie jeśli wolą korzystać -ffast-matematyki

Może moje pytanie powinno być raczej, czy jest jakiś sposób na wykorzystanie NaN lub jakiś inny „specjalny podwójny”, natomiast być w stanie włączyć wiele optymalizacji matematycznych bez zepsucia?

System to Linux/x64, gcc 4.8.1.

+4

Ten wątek może być pomocny [Mingw32 std :: isnan with -ffast-math] (http://stackoverflow.com/questions/7263404/mingw32-stdisnan-with-ffast-math) –

+0

@ShafikYaghmour Dzięki, że wątek jest pomocny. – stgtscc

+2

Istnieje również opcja użycia '-fno-skończonej-matematyki-tylko-łatającej-matematyki' http://lua-users.org/lists/lua-l/2009-04/msg00091.html –

Odpowiedz

4

Jeśli szukasz wartości, która byłaby propagowana przez operacje arytmetyczne, NaN jest nadal dostępna z opcją -ffast-math. Problem leży gdzie indziej. Dzięki -ffast-math niektóre operacje mogą zostać usunięte z obliczeń z powodu optymalizacji, a następnie nie ma możliwości zagwarantowania, że ​​będą one propagowane.

Na przykład, następujący, z -ffast-math zestawu spowoduje trudne do pisania 0.0n i nie ma szczególny stosunek do n które chronią przed nim.

float n = NAN; 
n *= 0.0; 

Jedną rzeczą, jaką można zrobić, jest użycie -fno-finite-math-only -ftrapping-math z -ffast-math jak Shafik Yaghmour powiedział. A drugi to, jeśli jest tylko kilka miejsc, w których spodziewasz się złej wartości, możesz sam to sprawdzić, umieszczając testy dokładnie w tych punktach.

Ostatnią opcją, którą mogę pomyśleć - jeśli naprawdę potrzebujesz optymalizacji - jest ręczne wprowadzenie wartości NaN (i może inf) do obliczeń i sprawdzenie, jak długo są one propagowane. Następnie w miejscach, w których propagacja się zatrzymuje, należy przetestować wystąpienie. - Jest to niebezpieczna metoda, ponieważ nie jestem w stu procentach pewna, czy mogę wymagać warunkowego przepływu operacji. Jeśli tak, istnieje znaczna szansa, to rozwiązanie będzie nieważne. Jest to ryzykowne i jeśli zostanie wybrane, wymaga bardzo ciężkich testów obejmujących wszystkie gałęzie obliczeń.

Normalnie byłbym raczej przeciw ostatniego rozwiązania, ale w rzeczywistości jest szansa, NaN (inf) wartości będą propagowane chociaż cały lub prawie cały obliczeń, więc może dać wydajność Szukasz dla. Więc możesz zaryzykować.


Sprawdzanie NaN z -ffast-math można zrobić, jak Shafik Yaghmour powiedział z

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

i double z

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

Sprawdzanie inf byłoby

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; 
} 

Można również połączyć isnan i isinf.