Verwendung von Gleitkommazahlen im Linux-Kernel


83

Ich lese Robert Loves "Linux Kernel Development" und bin auf folgende Passage gestoßen:

Keine (einfache) Verwendung von Gleitkommazahlen

Wenn ein User-Space-Prozess Gleitkomma-Anweisungen verwendet, verwaltet der Kernel den Übergang vom Ganzzahl- zum Gleitkomma-Modus. Was der Kernel bei der Verwendung von Gleitkommaanweisungen tun muss, hängt von der Architektur ab. Der Kernel fängt jedoch normalerweise eine Falle und leitet dann den Übergang vom Ganzzahl- zum Gleitkommamodus ein.

Im Gegensatz zum User-Space bietet der Kernel nicht den Luxus einer nahtlosen Unterstützung für Gleitkommazahlen, da er sich nicht leicht selbst einfangen kann. Die Verwendung eines Gleitkommas im Kernel erfordert unter anderem das manuelle Speichern und Wiederherstellen der Gleitkommaregister. Die kurze Antwort lautet: Tu es nicht! Außer in den seltenen Fällen befinden sich keine Gleitkommaoperationen im Kernel.

Ich habe noch nie von diesen Modi "Ganzzahl" und "Gleitkomma" gehört. Was genau sind sie und warum werden sie gebraucht? Gibt es diese Unterscheidung bei gängigen Hardwarearchitekturen (wie x86) oder ist sie spezifisch für einige exotischere Umgebungen? Was genau bedeutet ein Übergang vom Integer- zum Gleitkomma-Modus, sowohl aus Sicht des Prozesses als auch des Kernels?



2
Das Buch verwirrt das Thema ein wenig, indem es über einen "Modus" spricht. Die Ganzzahlanweisungen sind immer verfügbar, die FPU kann jedoch ganz oder teilweise deaktiviert werden. Keine nützliche Funktion bestand jemals vollständig aus FP-Operationen. Beispielsweise werden alle Steueranweisungen als "Ganzzahl" betrachtet. Siehe unten für mehr.
DigitalRoss

@ DigitalRoss: Ich stimme der Terminologie zu. Vielen Dank für die Antwort Übrigens, es machte die Dinge kristallklar.
NPE

Es wäre interessant zu wissen, woher der Wunsch nach Gleitkommaoperationen im Kernel stammt. Es ist verlockend, "schlechtes Design" in dem Sinne zu sagen, dass versucht wird, etwas im Kernel zu tun, das außerhalb des Kernels ausgeführt werden sollte, aber vielleicht gibt es Dinge, die ein Kernel wirklich tun sollte, wenn die Nutzung der FPU eine innovative Lösung wäre?
Chris Stratton

2
Da es niemand erwähnt hat, müssen Sie bei Verwendung von FP (oder SIMD) im Kernel / vor / nach Ihrem Code aufrufenkernel_fpu_begin()kernel_fpu_end() , um sicherzustellen, dass der FPU-Status des Benutzerbereichs nicht beschädigt wird. Dies ist, was Linux- mdCode für RAID5 / RAID6 tut.
Peter Cordes

Antworten:


86

Weil...

  • Viele Programme verwenden kein Gleitkomma oder verwenden es nicht für eine bestimmte Zeitscheibe. und
  • Das Speichern der FPU-Register und anderer FPU-Zustände benötigt Zeit. deshalb

... kann ein Betriebssystemkern die FPU einfach ausschalten. Presto, kein Status zum Speichern und Wiederherstellen und daher schnellerer Kontextwechsel. (Dies ist, was Modus bedeutete, es bedeutete nur, dass die FPU aktiviert wurde.)

Wenn ein Programm eine FPU-Operation versucht, wird das Programm in den Kernel eingefangen, der Kernel schaltet die FPU ein, stellt den möglicherweise bereits vorhandenen gespeicherten Status wieder her und kehrt dann zurück, um die FPU-Operation erneut auszuführen.

Zum Zeitpunkt des Kontextwechsels weiß es, dass es tatsächlich die Statusspeicherlogik durchläuft. (Und dann kann es die FPU wieder ausschalten.)

Übrigens glaube ich, dass die Erklärung des Buches aus dem Grund, warum Kernel (und nicht nur Linux) FPU-Operationen vermeiden, ... nicht ganz korrekt ist. 1

Der Kernel kann in sich selbst einfangen und tut dies für viele Dinge. (Timer, Seitenfehler, Gerätealarme, andere) . Der wahre Grund ist , dass der Kern vor allem nicht braucht FPU ops und muss auch ohne FPU überhaupt auf Architekturen laufen. Daher wird einfach die Komplexität und Laufzeit vermieden, die zum Verwalten des eigenen FPU-Kontexts erforderlich sind, indem keine Operationen ausgeführt werden, für die es immer andere Softwarelösungen gibt.

Es ist interessant festzustellen, wie oft der FPU-Status gespeichert werden müsste, wenn der Kernel FP verwenden möchte . . . Jeder Systemaufruf, jeder Interrupt, jeder Wechsel zwischen Kernel-Threads. Selbst wenn gelegentlich Kernel-FP 2 benötigt würde , wäre es wahrscheinlich schneller, dies in Software zu tun.


1. Das heißt, absolut falsch.
2. Ich kenne einige Fälle, in denen Kernel-Software eine Gleitkomma-Arithmetik- Implementierung enthält. Einige Architekturen implementieren herkömmliche FPU-Operationen in Hardware, überlassen jedoch einige komplexe IEEE-FP-Operationen der Software. (Denken Sie: Denormale Arithmetik.) Wenn ein seltsamer IEEE-Eckfall auftritt, werden sie in einer Software abgefangen, die eine pedantisch korrekte Emulation der Operationen enthält, die abfangen können.


16

Bei einigen Kernel-Designs werden die Gleitkommaregister nicht gespeichert, wenn eine "Kernel" - oder "System" -Aufgabe ausgeschaltet wird. (Dies liegt daran, dass die FP-Register groß sind und sowohl Zeit als auch Platz zum Sparen benötigen.) Wenn Sie also versuchen, FP zu verwenden, werden die Werte zufällig "puffen".

Darüber hinaus verlassen sich einige Hardware-Gleitkomma-Schemata darauf, dass der Kernel "Oddball" -Situationen (z. B. Nullteilung) über einen Trap behandelt, und der erforderliche Trap-Mechanismus befindet sich möglicherweise auf einer höheren "Ebene" als die derzeit ausgeführte Kernel-Task.

Aus diesen (und einigen weiteren) Gründen werden einige Hardware-FP-Schemata abgefangen, wenn Sie zum ersten Mal in einer Aufgabe einen FP-Befehl verwenden. Wenn Sie FP verwenden dürfen, wird in der Aufgabe ein Gleitkomma-Flag aktiviert. Wenn nicht, werden Sie vom Exekutionskommando erschossen.


Verwenden Sie unter Linux kernel_fpu_begin()/ kernel_fpu_end()vor / nach Ihrem Code, um das Speichern / Wiederherstellen des FPU-Status des Benutzerbereichs auszulösen (und ich schätze Ihren Kernel-FPU-Status gegen Vorkauf).
Peter Cordes
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.