2013-07-12 5 views
10

Da die gcc Option verwendet -ffast-math effektiv deaktiviert NaN und -/+inf, ich suche vielleicht die nächste beste Option für NaN in meinem leistungskritischen Mathe Code darstellt. Idealerweise würde der Sentinel-Wert, wenn er bearbeitet wird (add, mul, div, sub usw.), den Sentinel-Wert ergeben, wie es NaN tun würde, aber ich bezweifle, dass dies möglich wäre, da ich denke, NaN ist der einzige Wert, der dies erreicht. -0.0 vielleicht nicht eine gute Passform sein, wie es auch in -ffast-math deaktiviert ist und bestimmte Optimierungen wie (x+0.0) verhindern könnte, etc ..Gut Sentinel-Wert für Doppel vorziehen, wenn -ffast-math

Vielleicht ist meine Frage eher sein sollte, eine Möglichkeit ist es NaN oder eine andere „spezielle Doppel“, während zu verwenden in der Lage zu sein, viele der mathematischen Optimierungen zu ermöglichen, ohne zu brechen?

System ist Linux/x64, gcc 4.8.1.

+4

Dieser Thread kann hilfreich sein [Mingw32 std :: isnan mit -ffst-math] (http://stackoverflow.com/questions/7263404/mingw32-stdisnan-with-ffast-math) –

+0

@ShafikYaghhmour Danke, dieser Thread ist hilfreich. – stgtscc

+2

Es gibt auch die Option '-fno-endliche-nur-Mathematik -ftrapping-math' zu verwenden http://lua-users.org/lists/lua-l/2009-04/msg00091.html –

Antwort

4

Wenn Sie nach einem Wert suchen, der sich durch arithmetische Operationen ausbreiten würde, steht NaN immer noch mit der Option -ffast-math zur Verfügung. Das Problem liegt woanders. Mit -ffast-math können einige Operationen aufgrund der Optimierung aus der Berechnung entfernt werden, und dann gibt es keine Möglichkeit zu garantieren NaN oder jeder andere Wert würde propagiert werden.

Zum Beispiel die folgenden, mit -ffast-math gesetzt, wird dazu führen, hart 0.0 in n zu schreiben und es gibt keinen besonderen Wert für n die von ihm schützen würde.

float n = NAN; 
n *= 0.0; 

Eine Sache, die Sie tun können, ist -fno-finite-math-only -ftrapping-math mit -ffast-math zu verwenden, wie Shafik Yaghmour sagte. Und der andere ist, wenn es nur wenige Orte gibt, an denen Sie einen schlechten Wert erwarten, können Sie selbst nachprüfen, indem Sie Tests genau in diese Punkte setzen.

Die letzte Option, die ich denken kann - wenn Sie wirklich dringend Optimierung benötigen - ist manuell injizieren NaN (und vielleicht inf) Werte in die Berechnung und prüfen, wie lange es propagiert wird. Dann an den Orten, wo die Ausbreitung stoppt, Test für NaN (inf) Auftreten. - Dies ist eine unsichere Methode, da ich mich nicht hundertprozentig sicher bin, kann -ffast-math bedingten Fluss von Operationen beinhalten. Wenn es möglich ist, besteht eine erhebliche Chance, dass diese Lösung ungültig ist. Es ist also riskant und erfordert, wenn es ausgewählt wird, sehr schwere Tests, die alle Zweige der Berechnung abdecken.

Normalerweise wäre ich eher gegen die letzte Lösung, aber tatsächlich gibt es eine Chance, NaN (inf) Werte werden über die gesamte Berechnung oder fast ganz verbreitet, so dass es die Leistung geben kann, die Sie suchen. Sie möchten vielleicht das Risiko eingehen.


Überprüfung auf NaN mit -ffast-math Sie tun können, als Shafik Yaghmour sagte mit

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

und für double mit

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

Überprüfung auf inf wäre

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

Sie können auch isnan und isinf zusammenführen.