Numpy: bedeutungslos RuntimeWarning von clang-compiled np.float32 .__ mul__

Erstellt am 27. Apr. 2017  ·  53Kommentare  ·  Quelle: numpy/numpy

In Sagemath begegnen wir in unserem Ticket # 22799

RuntimeWarning: invalid value encountered in multiply

beim Multiplizieren einer numpy.float32 -Zahl mit nicht numpy Daten; dh numpy sollte diese Multiplikation nicht stillschweigend durchführen, und tatsächlich, wenn man mit gcc baut oder wenn es anstelle von np.float32 np.float oder np.float128 .

Genauer gesagt erhält man die Warnung vom Python-Aufruf

type(numpy.float32('1.5')).__mul__(numpy.float32('1.5'), x)

Dabei ist x ein univariates Sagemath-Polynom mit Koeffizienten im Sagemath-Typ RealField . (und nur diese bestimmte Art von Daten löst dies aus).
Das heißt, möglicherweise können solche bedeutungslosen Warnungen außerhalb von Sagemath ausgegeben werden. Wir können es unter OSX 11.12 mit seinem Standard-CC (einige Ableitungen von Clang 3.8) sowie unter Linux mit Clang 4.0 und unter FreeBSD 11.0 mit Clang 4.0 oder Clang 3.7 reproduzieren.

Möglicherweise sollten wir in der Lage sein, einen Weg zu finden, dies außerhalb von Sagemath zu reproduzieren, obwohl wir einige Tipps benötigen würden, wo in numpy Code dieses __mul__ tatsächlich implementiert ist, um zu sehen, welche Funktionen auf x angewendet werden ...

Wir sehen dies auch bei Numpy 1.11 und 1.12.

Alle 53 Kommentare

gleiches Bild mit numpy.float32('1.5').__mul__(x) sowie __add__ und __sub__ .

Diese Art von Fehler ist typisch für Arrays, die nan oder infinity . Was gibt np.array(x) zurück?

@ eric-wieser: es gibt array(x, dtype=object) , keine Warnungen.

Gibt np.multiply(np.float32('1.5'), x) dieselbe Warnung aus?

numpy.multiply(numpy.float32('1.5'), x) gibt die gleiche Warnung aus.

Was ist mit type(x).__rmul__(numpy.float32('1.5'), x) ?

Wenn Sie warnings.filterwarnings('error') ausführen könnten, würden Sie auch eine vollständige Stapelverfolgung erhalten

type(x).__rmul__(numpy.float32('1.5'), x)

TypeError: descriptor '__rmul__' requires a 'sage.structure.element.Element' object but received a 'numpy.float32'

x.__rmul__(numpy.float32('1.5')) geht gut durch.

Scheint, als hätte ich vergessen, wie rmul funktioniert. Ich meinte type(x).__rmul__(x, numpy.float32('1.5')) , aber ich stelle mir vor, dass dies dasselbe tut wie x.__rmul__ , es sei denn, x ist wirklich komisch

Scheitert das auch? np.multiply(np.array(1.5, dtype=object), x) (diesmal bitte mit filterwarnings )

type(x).__rmul__(x,numpy.float32('1.5')) geht ohne Vorwarnung durch.

Übrigens, das Setzen von warnings.filterwarnings('error') gibt mir nichts Interessantes,

---------------------------------------------------------------------------
RuntimeWarning                            Traceback (most recent call last)
<ipython-input-50-b3ece847d318> in <module>()
sage: np.multiply(np.array(1.5, dtype=object), x)
---------------------------------------------------------------------------
RuntimeWarning                            Traceback (most recent call last)
<ipython-input-52-706823a0b5a2> in <module>()
----> 1  np.multiply(np.array(RealNumber('1.5'), dtype=object), x)

RuntimeWarning: invalid value encountered in multiply

Hmm, Salbei hat etwas getan, was ich dort nicht erwartet hatte. Das gleiche Verhalten mit float('1.5') , würde ich vermuten?

Ok, also hier ist was ich denke passiert:

  • numpy verwendet die Objektschleife im Ufunc korrekt, wodurch nur PyNumber_Multiply aufgerufen wird
  • Innerhalb von sage setzt etwas das Fehlerflag in der FPU (Bug in Sage?)
  • numpy führt beim Beenden des Ufunc (Fehler in Objektschleifen?) Seine normale fpu-Flag-Prüfung durch und findet den Fehler, der von sage hinterlassen wurde
sage: float(1.5).__mul__(x)
NotImplemented
sage: np.float(1.5).__mul__(x)
NotImplemented
sage: np.float32(1.5).__mul__(x)
/usr/home/dima/Sage/sage/src/bin/sage-ipython:1: RuntimeWarning: invalid value encountered in multiply
  #!/usr/bin/env python
1.50000000000000*x
sage: np.float64(1.5).__mul__(x)
/usr/home/dima/Sage/sage/src/bin/sage-ipython:1: RuntimeWarning: invalid value encountered in multiply
  #!/usr/bin/env python
1.50000000000000*x

Erwähnenswert ist, dass np.float is float aus Kompatibilitätsgründen

Warum gibt np.float32(1.5).__mul__(x) NotImplemented ?

Weil es weiß, dass es mit einer Objektschleife als np.multiply umgehen kann, und es dann erneut mit float * x in dieser Schleife versucht. Leider nimmt der Wrapper um diese Schleife FPU-Flags auf, die von Salbei gesetzt wurden.

Wenn Sie genau hinschauen, werden Sie feststellen, dass x.__rmul__ immer noch tiefer im Stapel aufgerufen wird

sage: np.float32(1.5)*x
/usr/home/dima/Sage/sage/src/bin/sage-ipython:1: RuntimeWarning: invalid value encountered in multiply
  #!/usr/bin/env python
1.50000000000000*x
sage: np.float128(1.5)*x
1.50000000000000*x
sage: np.float64(1.5)*x
/usr/home/dima/Sage/sage/src/bin/sage-ipython:1: RuntimeWarning: invalid value encountered in multiply
  #!/usr/bin/env python
1.50000000000000*x

es sieht also so aus, als ob np.float128 in Ordnung ist, aber

sage: np.float128(1.5).__mul__(x)
/usr/home/dima/Sage/sage/src/bin/sage-ipython:1: RuntimeWarning: invalid value encountered in multiply
  #!/usr/bin/env python
1.50000000000000*x

Das ist komisch. Vielleicht ein Compiler-Fehler (wie wir ihn auf gcc nie sehen), aber an welcher Stelle?

Das FPU-Flag wird aus irgendeinem Grund auf clang gesetzt, aber nicht auf gcc innerhalb des Salbei-Codes, wie es scheint. Numpy ist schuld daran, dass er Lärm gemacht hat, aber ich bezweifle sehr, dass er schuld daran ist, dass er es überhaupt eingestellt hat.

Leider bietet numpy keine Möglichkeit, explizit nach den FPU-Flags zu fragen - das wäre sehr hilfreich, um das Problem innerhalb von sage zu halbieren.

Ich gehe davon aus, dass dies die gleiche Warnung verursacht (benötigt dazu numpy 1.12, denke ich)

mul = np.vectorize(x.__rmul__)
mul(float('1.5'))

nicht ganz das gleiche, aber nah:

/usr/home/dima/Sage/sage/local/lib/python2.7/site-packages/numpy/lib/function_base.py:2652: RuntimeWarning: invalid value encountered in __rmul__ (vectorized)
  outputs = ufunc(*inputs)
array(1.50000000000000*x, dtype=object)

OK, gut, dies scheint darauf hinzudeuten, dass es mit np.float32 oder np.float64 nichts Bestimmtes gibt. Es ist ein allgemeinerer Numpy-Mechanismus, um hier auftretende Warnungen zu generieren.

Ich weiß nicht, dass die Compilerautoren es als Fehler betrachten würden. Die Art und Weise, wie die Warnung funktioniert, besteht darin, dass der Prozessor einige magische Statusflags verfolgt, die automatisch gesetzt werden, wenn das entsprechende Ereignis eintritt. Numpy löscht sie, bevor die Berechnung gestartet wird, und überprüft sie am Ende erneut. Irgendwo zwischen diesen Punkten führt die durch Klirren erzeugte Baugruppe eine Berechnung durch, die eine NaN beinhaltet. Aber es ist schwer zu finden (da die eigentliche Flag-Einstellung vollständig in Hardware erfolgt), und die meisten Leute machen sich keine Sorgen darüber, wie sich ihr Code auf die fpu-Flags auswirkt. (Libm-Implementierungen sind auch notorisch inkonsistent, ob sie diese Flags setzen.) Und die genauen Ergebnisse hängen stark von der genauen asm ab, die generiert wird. Daher ist es nicht verwunderlich, dass Sie sie nur in bestimmten Konfigurationen und nicht in anderen sehen.

Ja, das bestätigt meinen Verdacht und bietet Ihnen eine Möglichkeit zum Debuggen. Dieser Code

def check_fpu(f):
    @functools.wraps(f)
    def wrapped(*args, **kwargs):
        excluded = list(range(len(args))) + list(kwargs.keys())
        fvec = np.vectorize(f, excluded=excluded)
        return fvec(*args, **kwargs)
    return wrapped

Auf eine Python-Funktion angewendet, können Sie die Warnungen auf diesen Codeabschnitt beschränken.

Ich meine, es ist ziemlich seltsam, dass es überhaupt passiert; Compiler erfinden NaNs normalerweise nicht und werfen sie dann ohne Grund weg.

Wenn Sie versuchen, es aufzuspüren, sollten Sie sich wahrscheinlich den Code in Salbei ansehen, der die Multiplikation für diese Polynome implementiert - es ist wahrscheinlich, dass die seltsame Flag-Einstellung wahrscheinlich die ganze Zeit stattfindet, und Numpys einzige Beteiligung besteht darin, dies sichtbar zu machen .

Es gibt auch ein ziemlich gutes Argument, dass Numpy nicht einmal versuchen sollte, diese Flags in Objektschleifen zu überprüfen. (Oder ganzzahlige Schleifen, aber das ist schwierig, weil die Art und Weise, wie wir einen ganzzahligen Überlauf melden, ziemlich grob ist und die fpu-Flags verwendet.) Das ist das einzige, was ich mir vorstellen kann, dass diese Zahl hier tun könnte.

check_fpu() hat einen Tippfehler, es sollte dort fvec = np.vectorize(f, excluded=exclude) sein.
Und wir sind auf Python2: import functools32 as functools .

functools.wraps braucht Python 3 nicht, oder?

Ich erhalte eine Fehlermeldung, wenn ich die Funktionswerkzeuge von python2 in setattr() call verwende

AttributeError: 'method-wrapper' object has no attribute '__module__'

Ja, ich vermute, es ist die Bibliothek mit mehreren Genauigkeiten, die die Arithmetik für die Koeffizienten in RealField implementiert, die das FPU-Flag setzt. Werden die zugrunde liegenden Bibliotheken unter den verschiedenen Umständen mit demselben Compiler wie numpy kompiliert? Oder wird nur Numpy mit den verschiedenen Compilern neu erstellt?

Ja, ich vermute, es ist jede Bibliothek mit mehreren Genauigkeiten, die die Arithmetik für die Koeffizienten in RealField implementiert

Das ist MPFR für die Aufzeichnung.

Wir versuchen, Sagemath auf clang + gfortran zu portieren (hauptsächlich unter OSX und FreeBSD, Plattformen, auf denen clang der primäre Compiler ist), damit das Erstellen und Ausführen unter OSX einfacher und schneller ist (FreeBSD ist eher ein Tool, um eine ähnliche Umgebung ohne zu erhalten der Ärger mit OSX- und Apple-Hardware).

Alle Vergleiche, die ich hier berichte, beziehen sich auf vollständige Builds mit clang / clang +++ gfortran im Gegensatz zu gcc / g +++ gfortran.

Der Wrapper scheint uns zu sagen, dass x.__rmul__ das FPU-Flag setzt

check_fpu(x.__rmul__)(np.float32('1.5'))

druckt die Warnung aus, x.__rmul__(np.float32('1.5')) nicht.

In der Tat - meine Annahme war, dass x.__rmul__ in Python geschrieben wurde und dass sein Quellcode halbiert werden kann, um herauszufinden, welches Bit das Flag spezifisch setzt

x.__rmul__ ist in Cython, aber es ist immer noch ein kleiner Code, den man untersuchen muss.

Wenn es eine einfache Möglichkeit gibt, die Warnung in einen Fehler umzuwandeln, erhalten Sie einen Traceback (Cython generiert Tracebacks für Fehler, jedoch nicht für Warnungen).

@jdemeyer IMHO numpy Warnung wird viel später im Codepfad ausgegeben, dh es ist das Ergebnis einer expliziten Überprüfung der FPU-Flags, nicht eines Interrupt-Sets.

numpy bietet eine Schnittstelle, um diese Warnung in einen Fehler umzuwandeln. Sie erhalten jedoch nur die Möglichkeit, ohne jegliche Rückverfolgung zur Haupt-iPython-Interpreter-Schleife zurückzukehren.

@jdemeyer Würde Cython-Code zwischen sig_on() / sig_off() von Cysignals eine Ausnahme

cysignals würde eine Ausnahme auslösen, wenn SIGFPE ausgelöst wird. Dies kann passieren, wenn ein FPU-Flag gesetzt wird, abhängig von der FPU-Konfiguration. Standardmäßig ist dies jedoch nicht der Fall.

Eine ähnliche Warnung: RuntimeWarning: invalid value encountered in greater ist
kommt von np.float64(5)>e . Hier ist e die Sagemath-Konstante, die die Basis des natürlichen Logarithmus 2.71828 angibt ... und auf dem Weg zur Bewertung auf True muss sie "konvertiert" werden (sicherlich, e "weiß "seine numerische Annäherung, es ist e.n() ) zu einer Zahl.
Diese Annäherung ist vom Typ RealField bereits oben erwähnt wurde (daher ist diese Warnung möglicherweise eng miteinander verbunden).

Wieder ist die Frage: Was macht numpy , um np.float64(5)>e zu bewerten?
Oder gleichwertig, die gleiche Warnung wird von np.float64(5).__gt__(e) , sodass man genauso gut von dort aus beginnen kann.

Beachten Sie, dass type(e) sage.symbolic.constants_c.E ; Es ist im Grunde eine (fast) Dummy-Klasse
Umschließen von Sagemaths symbolischen Ausdrücken ( SR ).

Es gibt keine Warnungen von np.float64(5).__gt__(e.n()) oder np.float64(5)>e.n() .
Im Wesentlichen passiert dasselbe (gleiche Warnung / kein Warnmuster), wenn Sie e durch pi ersetzen (mit offensichtlichen pi.n()==3.1.415... ).
pi hat den Typ SR , dh sage.symbolic.expression.Expression .

Die Antwort ist hier dieselbe - numpy ruft np.greater mit einer Objektschleife auf. Auf der untersten Ebene heißt das e.__lt__(5.0) . Aber noch einmal, es überprüft die FPU-Flags vorher und nachher und stellt fest, dass etwas nicht stimmt.

Die meisten arithmetischen / logischen Operatoren von ndarray (mit Ausnahme von - und divmod ) delegieren an ufuncs. Wenn dies mit weisen Objekten aufgerufen wird, werden die O (Objekt-) Schleifen für diese Ufuncs aufgerufen. Diese Objektschleifen durchlaufen das Array (in diesem Fall 0d), führen den normalen Python-Operator für die Elemente aus, suchen jedoch nach FPU-Flags, wenn dies der Fall ist.

Salbei setzt also wieder diese Flaggen. Vielleicht ist dies ein Zeichen für einen Fehler, vielleicht nicht.

Ich denke, hier gibt es ein gutes Argument, dass numpy die fpu-Flags für diese Fälle nicht überprüfen sollte. @njsmith , denkst du, wir sollten die Prüfung auf Objekttypen entfernen?

Tatsächlich ist e.__lt__(5.0) ein symbolischer Ausdruck:

sage: type(e.__lt__(np.float32(5.0)))
<type 'sage.symbolic.expression.Expression'>
sage: e.__lt__(np.float32(5.0))
e < 5.0
sage: bool(e.__lt__(np.float32(5.0)))  # this is how it's evaluated
True

und daher bezweifle ich wirklich, dass es am Ende aufgerufen wird, denn man bekommt True . Außerdem lässt Ihr check_fpu -Wrapper von oben keine Warnungen drucken, dh das Folgende funktioniert einfach.

sage: check_fpu(e.__lt__)(np.float32(5.0))
e < 5.0

Ich konnte unser Problem in Sagemath mit dem fpectl Python-Modul (das unter FreeBSD etwas, aber nicht vollständig kaputt ist) auf eine bestimmte C-Erweiterung

IMHO fpectl ist so nützlich, dass es behoben werden sollte ; Vielleicht sogar in Numpy anstelle von oder zusätzlich zu np.seterr() , da es eine bessere Granularität für kompilierte Komponenten bietet.

Der Unterschied zwischen dem Ansatz von fpectl und np.seterr ist:

np.seterr führt die Ufunc-Schleife aus und prüft dann, ob Flags gesetzt sind.

fpectl macht etwas Magie, um es so zu machen, dass bei jedem Vorgang, bei dem eines der Flags gesetzt wird, die Hardware einen Interrupt auslöst, der Kernel diesen in ein an den Prozess geliefertes SIGFPE konvertiert und einen installiert SIGFPE-Handler, der longjmp direkt aus dem Signalhandler in den Fehlerbehandlungscode einfügt.

Einige Nachteile des fpectl -Ansatzes sind: (a) es funktioniert unter Windows überhaupt nicht, (b) es bricht nach Code, der intern bewirkt, dass eines dieser Flags vorübergehend gesetzt wird, und löscht es dann (dies) ist legal und ich gehe davon aus, dass es Libms gibt, die das tun), (c) longjmp ist unglaublich zerbrechlich; Grundsätzlich riskieren Sie jedes Mal einen Segfault, wenn Sie dies tun. Es kann sicherlich keine allgemeine Lösung für beliebige benutzerdefinierte Ufuncs sein.

Angesichts all dessen glaube ich nicht, dass Numpy wechseln wird.

In jedem Fall scheint das ursprüngliche Problem behoben zu sein. Schließen Sie dieses Problem. Sie können jederzeit ein neues Problem öffnen, wenn Sie Änderungen in seterr möchten.

In jedem Fall scheint das ursprüngliche Problem gelöst zu sein

Sind wir sicher, dass wir die Überprüfung der FPU-Flags auf Objektschleifen nicht deaktivieren möchten? Das scheint eine ziemlich vernünftige Änderung von numpy zu sein.

@ Eric-Wieser: Oh, das ist eine interessante Idee, ja. Vielleicht lohnt es sich, dafür eine Ausgabe zu eröffnen :-). Das "Richtige" ist jedoch ziemlich kompliziert - im Idealfall sollten wir den Objekt-D-Typ nicht speziell umhüllen (denken Sie an Benutzer-D-Typen), und Integer-Schleifen sollten ihn auch nicht verwenden (dies kann eine echte Optimierung bei einigen Architekturen sein, bei denen die Überprüfung durchgeführt wird / Das Löschen der FPU-Flags ist extrem langsam), aber Integer-Schleifen benötigen eine Möglichkeit, Integer-Fehler explizit zu signalisieren, was sie derzeit durch explizites Setzen der FPU-Flags tun. Ich bin mir nicht sicher, ob dies ein Fall ist, in dem es leicht niedrig ist -hängende Früchte?

Oder habe ich es falsch verstanden und Salbei hat nur das Problem identifiziert, und sie brauchen noch eine kleine Änderung, um es tatsächlich zu beheben?

@njsmith : Ich verstehe nicht, warum Sie sagen, dass es unter Windows nicht funktioniert. (Dies wäre jedoch in der Zeit vor C99 richtig). Moderne FPU-Handling-Funktionen (fenv) sind verfügbar, sobald Ihr C-Compiler dem C99-Standard entspricht. Abgesehen von fenv ist nur setjmp / longjmp erforderlich (wieder Standard-C-Funktion).

Ich bin auch neugierig auf eine Bibliothek, die im Verlauf einer normalen Operation eine der FE-Ausnahmen verursacht.
(Es sei denn, es ist als Fehler klassifiziert).

@dimpase : Sie benötigen auch SIGFPE-Unterstützung, die in C99 nicht angegeben ist. (Nun, C99 sagt, dass es ein SIGFPE geben sollte, aber das ist für das Teilen durch Null - es gibt keine Möglichkeit an, es mit Gleitkomma-Ausnahmen zu verbinden.) Das heißt, es sieht so aus, als hätte ich mich falsch erinnert, und zwar unter Windows MSVCRT unterstützt keine Signale, emuliert SIGFPE mithilfe der strukturierten Ausnahmebehandlung und bietet die nicht standardmäßige Funktion _control_fp , um sie für bestimmte fp-Ausnahmen zu aktivieren, sodass die Windows-Unterstützung eigentlich kein Hindernis darstellt. OTOH, es spielt keine Rolle, da longjmp definitiv nicht ohne einen sehr guten Grund passiert :-)

Und FWIW, wenn eine Bibliothek eine FE-Ausnahme verursacht und diese dann wieder gelöscht hat, kann ich nicht verstehen, warum sie das als Fehler betrachten würden. Ich bin mir nicht sicher, ob es solche Implementierungen gibt, aber es ist plausibel, und wenn dies der Fall ist, sagen wir b / c, dass uns jemand sagt, dass numpy auf Plattform X defekt ist und die einzige Lösung darin besteht, die Änderung rückgängig zu machen du schlugst vor.

Können Sie die Frage beantworten, die ich am Ende meines vorherigen Kommentars gestellt habe?

@njsmith : Wenn eine libm (oder ein anderer Benutzercode) eine FE-Ausnahme verursachen und verarbeiten muss, würde sie einen eigenen FE-Ausnahmebehandler einrichten, den vorherigen speichern und den vorherigen beim Beenden wiederherstellen.
Es ist also kein Problem, wenn der zugrunde liegende Code den Regeln entspricht.

In Bezug auf die MS-Unterstützung hierfür liefern sie fenv.h seit Visual C (++) 2013 oder so .
Es ist speziell für setjmp / longjmp gedacht (wie genau es unter der Haube gemacht wird, sollte einen nicht allzu sehr beunruhigen, hoffe ich).

In Bezug auf die Laufzeitwarnung von numpy:

  • Wenn Sie der Meinung sind, dass der Benutzercode mit FP-Flags schnell und locker abgespielt werden kann, sollten diese Warnungen höchstens optional sein.
  • Andernfalls können sie als Standard gehalten werden, aber zumindest ein Weg, um dem Ort auf den Grund zu gehen, von dem sie kommen, ist entscheidend, damit sie nützlich sind. (verbessert) fpectl ist ein schneller Weg, um Letzteres zu erreichen. Die Verwendung externer Tools (wie Debbugger, mit denen Sie den Code instrumentieren können, um nach jeder Anweisung etwas zu überprüfen) ist schwieriger, langsamer und fehleranfälliger - z. B. ist es nicht ungewöhnlich, dass der Fehler nur in einer optimierten Binärdatei auftritt, und verschwindet, sobald Sie versuchen, es auf einer gut debuggbaren Binärdatei zu finden.
  • In jedem Fall sollte es möglich sein, das RuntimeWarning-Ding auszuschalten.

In Bezug auf dieses Problem in Sage - wird immer noch behoben (hoffentlich ist es nur auf einige Probleme in

Tut mir leid, das geht im Kreis und ich muss zu anderen Dingen übergehen. Wenn also nichts Neues zum Thema fenv / sigfpe auftaucht, ist dies meine letzte Nachricht zu diesem Thema. (Ich bin immer noch daran interessiert, ob irgendetwas für den Weisen-Käfer zu tun ist).

Wenn eine Bibliothek (oder ein anderer Benutzercode) eine FE-Ausnahme verursachen und verarbeiten muss, würde sie einen eigenen FE-Ausnahmebehandler einrichten und den vorherigen speichern.

Sie schlagen vor, einen Vorgang auszuführen, bei dem normalerweise kein Signalhandler ausgelöst wird, und den Prozessor in einem nicht standardmäßigen Modus zu konfigurieren, in dem ein Signalhandler ausgelöst wird. Es ist völlig vernünftig, dass Code diesen Vorgang ausführt und erwartet, dass er überhaupt keinen Signalhandler auslöst.

In Bezug auf die MS-Unterstützung hierfür liefern sie fenv.h seit Visual C (++) 2013 oder so.
Es ist speziell für setjmp / longjmp gedacht

Ich kann nicht herausfinden, wovon du hier sprichst. Afaict, die Standardfunktionalität in fenv.h ist nur für die Implementierung von Funktionen im Numpy-Stil nützlich, und MS hält sich an den Standard. Ich sehe dort keine Funktionen, die überhaupt mit setjmp / longjmp verwendet werden könnten.

Benutzercode kann mit FP-Flags schnell und locker abgespielt werden, dann sollten diese Warnungen höchstens optional sein.

Das sorgfältige Löschen eines durch eine Zwischenberechnung gesetzten Flags ist das genaue Gegenteil davon, schnell und locker mit ihnen zu spielen. Auch die Warnungen sind optional.

Ein Weg, um dem Ort auf den Grund zu gehen, von dem sie kommen, ist entscheidend, damit sie nützlich sind. (verbessert) fpectl ist ein schneller Weg, um Letzteres zu erreichen.

Sie sind buchstäblich die erste Person in so etwas wie einem Jahrzehnt, die SIGFPE benötigt, um diese Art von Problem zu beheben. Wenn Sie sich die Kommentare zu den weisen Fehlern noch einmal ansehen, sieht es so aus, als hätten Sie fpectl nicht zum Laufen gebracht? Es soll keinen Core Dump verursachen. (Es sieht so aus, als ob cysignals den fpectl-Code überschreibt, sodass er nicht einmal ausgeführt wird.)

Wenn dies erneut auftritt, müssen Sie nur einen C-Aufruf ausführen, um SIGFPE zu aktivieren, und dann einen Debugger verwenden, um eine Stapelverfolgung abzurufen. Sie benötigen keinen Debug-Build, um einen Stack-Trace zu erhalten. Alles, was Sie tun müssen, ist, die Symbole nicht zu entfernen. Und hey, jetzt wissen wir, falls dies wieder auftaucht.

Ich verstehe, dass das Debuggen wirklich frustrierend war, aber es ist nicht hilfreich, darauf zu bestehen, dass andere Projekte die Basisinfrastruktur ändern oder warten müssen, wenn Sie nicht einmal klar erklären können, was damit erreicht wird. (Ich habe eigentlich keine Ahnung, wie Sie denken, wenn Sie hier etwas ändern, um diese Art von Fehler schneller zu finden. Die ganze Idee von longjmp besteht darin, die genaueren Informationen zu zerstören, von denen Sie sagen, dass Sie sie wollen.)

Schließlich stellt sich heraus, dass es sich um einen langjährigen Fehler im Clang C-Compiler handelt. Grundsätzlich ist in einem bestimmten Bereich von double eine Zuordnung wie in

unsigned long a;
double b;
...
a = b;

erhöht FE_INVALID (und manchmal FE_INEXACT ); Dies wirkt sich übrigens auch auf andere Arten von Float-Daten aus. Hervorragende MPFR (MPFR muss natürlich Doppel in ihre willkürlichen Präzisions-Floats kopieren) haben eine Problemumgehung bereitgestellt und dies für Salbei behoben.

Übrigens, ein noch länger bestehender Clang- Bug 8100 (seit 2010 mit einem Dutzend geschlossener Duplikate) besagt, dass es keine Hoffnung gibt, Clangs fenv.h zu verwenden, um fpectl im Moment richtig funktionieren zu lassen . Clang ist in dieser Hinsicht nicht vollständig C99-konform und ist sehr schüchtern.

Ich bin mir nicht sicher, ob numpy etwas dagegen unternehmen möchte. Vielleicht könnte eine Bemerkung hilfreich sein, dass RuntimeWarning lediglich auf einen Compiler-Fehler zurückzuführen ist (unter Berufung auf "Clang Bug 8100", es ist ein ziemlich prominentes Beispiel).

Fehler 8100 ist nicht relevant; Damit können die C99-Pragmas Gleitkomma-Optimierungen deaktivieren, und keine Mainstream-Compiler unterstützen diese. numpy scheint sowieso (meistens) zu funktionieren :-)

Der Geist des Fehlers 8100 ist, dass es Clang nicht darum geht, dass FP-Operationen korrekt kompiliert werden. obwohl ein Anwalt nicht zustimmen könnte. :-)

OK, der bereits erwähnte Fehler 17686 ist sicher relevant.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen