Python: Compiler-Optionen können bei Gleitkommaberechnungen zu Fehlern führen

Ein Wissenschaftler einer New Yorker Universität hat festgestellt, dass es bei einigen Python-Paketen zu Problemen mit numerischen Berechnungen kommen kann.

In Pocket speichern vorlesen Druckansicht 52 Kommentare lesen
Cybercrime

(Bild: dpa, Oliver Berg)

Lesezeit: 4 Min.
Von
  • Frank-Michael Schlede
Inhaltsverzeichnis

Eine ganze Reihe von Python-Paketen kann unter bestimmten Voraussetzungen falsche Ergebnisse bei Gleitkommaberechnungen liefern. Das hat Brendan Dolan-Gavitt festgestellt, der ist als Assistenz-Professor an der privaten Tandon-Universität in New York tätig. Er befasst sich laut seinem Twitter-Profil an dieser Universität vornehmlich mit Themen wie Sicherheit und Reverve Enineering.

Aufgeschreckt wurde Dolan-Gavitt, wie er in einem Blog-Eintrag ausführlich schildert, zunächst durch einige ungewöhnliche Warnmeldungen der NumPy-Bibliothek. Die Bibliothek dient dazu, Vektoren, Matrizen oder generell große mehrdimensionale Arrays einfacher zu handhaben. Diese Warnungen tauchten immer wieder auf, wenn er bestimmte Python-Pakete importierte. Das mag auf den ersten Blick nicht so erstaunlich scheinen, mehren sich doch in letzter Zeit die Meldungen zu Angriffen auf Pakete und Paketmanager in Zusammenhang mit der populären Programmiersprache.

Die immer wieder auftauchenden Warmeldungen beim Einbinden von bestimmten Python-Paketen brachten den Wissenschaftler auf die Spur der Probleme (Bild: Brendan Dolan-Gavitt).

Als Mathematiker konnte Dolan-Gavitt jedoch verifizieren, dass sich das Problem rund um die Gleitkomma-Subnormalen in seinem Python-Code drehte. Wer bereits einmal versucht hat, Einsatz, Funktionsweise und das Rechnen mit Gleitkommazahlen in möglichst einfachen Worten zu erläutern, wird Dolan-Gavitts Aussage, dass "Fließkommamathematik bekanntermaßen knifflig“ ist, sicher gerne bestätigen.

Er führt dazu weiter aus, dass alle möglichen seltsamen Probleme auftreten können, wenn irgendetwas das Verhalten der Fließkommaeinheit (FPU) auf der CPU verändert. So hängen unter anderem einige numerische Algorithmen vom Standardverhalten der FPU ab. Sie konvergieren nicht, wenn die FPU so eingestellt ist, dass sie subnormale/denormale Zahlen als Null behandelt. Das geschieht auf x86-Systemen durch Setzen der FTZ/DAZ-Flags im MXCSR-Register.

Das grundsätzliche Problem liegt laut Dolan-Gavitt darin, dass die sogenannten subnormalen Zahlen – die auch als nichtnormalisierte Fließkommazahlen bezeichnet werden – durch die Fehler als Null-Wert behandelt werden. Diese Zahlen besitzen eine 0 vor dem Binärpunkt, während bei den “normalen“ Fließkommazahlen an dieser Stelle immer eine 1 zu finden ist. Die subnormalen Zahlen bieten die Garantie, dass bei Addition und Subtraktion von Gleitkommazahlen niemals ein Unterlauf (underflow) zweier nahe beieinander liegende Gleitkommazahlen auftreten kann. Sie haben immer eine darstellbare Differenz ungleich Null.

Durch eine Suche fand der Wissenschaftler einen entsprechenden GitHub-Eintrag, der auf eine gemeinsam genutzte Bibliothek hinwies, die mit der gcc/clang-Option -ffast-math kompiliert und als Verursacher des Problems geladen wurde. Dabei stellte sich heraus, dass der Compiler bei Aktivierung dieser Option sogar bei gemeinsam genutzten Bibliotheken einen Konstruktor einbindet, der die FTZ/DAZ-Flags setzt, sobald die Bibliothek geladen wird.

Das bedeutet, dass jede Anwendung, die diese Bibliothek lädt, ihr Fließkommaverhalten für den gesamten Prozess ändert. Zudem aktiviert die Option -Ofast, die auf den ersten Blick nach einem "Mach mein Programm schnell"-Flag klingt, automatisch -ffast-math, sodass einige Projekte es unwissentlich aktivieren, ohne dass ein Entwickler oder eine Entwicklerin sich der Auswirkungen bewusst ist.

Eine Überprüfung der Bibliotheken, die das Programm von Dolan-Gavitt im Python-Prozess geladen hat, brachte das Ergebnis, dass die Netzwerkbibliothek gevent der Verursacher der Probleme war. Eine weitere Suche zeigte, dass bereits ein Bugreport mitsamt dem Versuch eines Fix existiert, dieser aber nicht funktioniert. Auf diese Weise bringt die aktuelle Version von gevent auf PyPI immer noch das Fließkommaverhalten durcheinander.

Der Informatiker versuchte danach festzustellen, welche anderen Pakete und Bibliotheken von diesem Problem betroffen sind. In seinem ausführlichen Blog-Eintrag beschreibt er diese Suche, die sich als umfangreich und schwierig erwies. Er gibt dort auch einige Empfehlungen, wie Entwicklerinnen und Entwickler mit diesem Problem, das nach seiner Schätzung etwa 2500 Python-Pakete betreffen könnte, umgehen sollten. Seine Forderung ist es abschließend, das Verhalten der Compiler für diese Fälle zu ändern. Allerdings weist er auch darauf hin, dass ein entsprechender Bug-Report für den GCC-Compiler nun schon fast 10 Jahre alt ist, ohne dass dieser Fehler behoben wurde. (fms)