Was ist der Unterschied zwischen harten und weichen Gleitkommazahlen?
98
Wenn ich C-Code mit meiner Cross-Toolchain kompiliere, druckt der Linker Seiten mit Warnungen, die besagen, dass meine ausführbare Datei Hard Floats verwendet, meine Libc jedoch Soft Floats. Was ist der Unterschied?
Wenn es sich um eine ARM-Architektur handelt, setzen Sie diese bitte in die Tags :-)
Nils Pipenbrinck
3
@Nils Pipenbrinck: MIPS-Chips haben auch dieses Problem
Javier
Antworten:
100
Harte Schwimmer verwenden eine On-Chip-Gleitkommaeinheit. Soft Floats emulieren einen in Software. Der Unterschied ist die Geschwindigkeit. Es ist seltsam zu sehen, dass beide auf derselben Zielarchitektur verwendet werden, da der Chip entweder eine FPU hat oder nicht. Sie können Soft-Floating Point in GCC mit -msoft-float aktivieren. Möglicherweise möchten Sie Ihre libc neu kompilieren, um Hardware-Gleitkomma zu verwenden, wenn Sie es verwenden.
"Es ist seltsam zu sehen, dass beide auf derselben Zielarchitektur verwendet werden." Dies kann sinnvoll sein, wenn eine Bibliothek in genauheitskritischen Teilen maschinenunabhängig und bitgenau (Soft Float) und in Teilen, in denen kleine Abweichungen auftreten, schnell (Hard Float) ist ist egal.
PhilLab
Es passiert auf 32-Bit-ARM.
Aaron Franke
31
Es gibt drei Möglichkeiten, Gleitkomma-Arithmetik durchzuführen:
Verwenden Sie Float-Anweisungen, wenn Ihre CPU über eine FPU verfügt. (schnell)
Lassen Sie Ihren Compiler Gleitkomma-Arithmetik in Ganzzahl-Arithmetik übersetzen. (langsam)
Verwenden Sie Float-Anweisungen und eine CPU ohne FPU. Ihre CPU generiert eine Ausnahme (Reserved Instruction, Unimplemented Instruction oder ähnliches). Wenn Ihr Betriebssystemkern einen Gleitkomma-Emulator enthält, emuliert er diese Anweisungen (am langsamsten).
Genau genommen scheinen mir all diese Antworten falsch zu sein.
Wenn ich C-Code mit meiner Cross-Toolchain kompiliere, druckt der Linker Seiten mit Warnungen, die besagen, dass meine ausführbare Datei Hard Floats verwendet, meine Libc jedoch Soft Floats. Was ist der Unterschied?
Das Debian VFP-Wiki enthält Informationen zu den drei Auswahlmöglichkeiten für -mfloat-abi:
soft - Das ist reine Software
softfp- Dies unterstützt eine Hardware-FPU, aber der ABI ist soft-kompatibel.
hard- Der ABI verwendet Float- oder VFP- Register.
Der Linker (Loader) -Fehler liegt daran, dass Sie über eine gemeinsam genutzte Bibliothek verfügen, die Gleitkommawerte in Ganzzahlregistern übergibt. Sie können immer noch Ihren Code mit einem kompilieren -mfpu=vfp, etc , aber Sie sollten verwenden , -mfloat-abi=softfpso dass , wenn die libc einen Schwimmer muss es in einer Weise geleitet wird , die Bibliothek versteht.
Der Linux-Kernel kann die Emulation der VFP-Anweisungen unterstützen. Offensichtlich ist es -mfpu=nonefür diesen Fall besser, mit zu kompilieren, und die Kompilierung lässt Code direkt generieren, anstatt sich auf eine Linux-Kernel-Emulation zu verlassen. Ich glaube jedoch nicht, dass der Fehler des OP tatsächlich mit diesem Problem zusammenhängt. Es ist getrennt und muss auch zusammen mit dem behandelt werden -mfloat-abi.
Die gemeinsam genutzte Armv5-Bibliothek mit ArmV7-CPU ist das Gegenteil von dieser. Die libc war hart schwebend, aber die Anwendung war nur weich . Es gibt einige Möglichkeiten, um das Problem zu umgehen, aber das Neukompilieren mit den richtigen Optionen ist immer am einfachsten.
Ein weiteres Problem besteht darin, dass der Linux-Kernel VFP-Tasks (oder einen beliebigen vorhandenen ARM-Gleitkomma) unterstützen muss, um die Register auf einem Kontextwechsel zu speichern / wiederherzustellen.
Moderne GCC-Versionen (~ 4.8 +) unterstützen 'multi-lib' mit Hard-Float- und Soft-Float-Bibliotheken. Frühere Versionen erforderten, dass Sie einen Compiler mit einer bestimmten Version erstellen ließen. Gelegentlich wird der Pfad zur richtigen Bibliothek benötigt, wenn eine Verknüpfung mit einer 'multi-lib'-gcc-Distribution hergestellt wird, da es mehrere Versionen der Bibliotheken gibt (für die Erstellung des Compilers ist eine längere Zeit erforderlich). Verzeichnisnamen können "hf", "hardf", "libhf" oder "hard-float" sein, befinden sich jedoch normalerweise im regulären "soft" -Verzeichnis oder an einem nahe gelegenen Ort.
Kunstloser Lärm
Das ist die richtige Antwort. Die aufrufende Konvertierung für Floats muss zwischen Ihrem Code und libc übereinstimmen. Es funktioniert möglicherweise immer noch mit einer Nichtübereinstimmung, wenn Sie niemals Gleitkomma-Libc-Funktionen aufrufen.
Tor Klingberg
13
Es hört sich so an, als ob Ihre libc für Software-Gleitkommaoperationen erstellt wurde, während Ihre exe unter der Annahme der Hardwareunterstützung für Gleitkomma kompiliert wurde. Kurzfristig könnten Sie Soft Floats als Compiler-Flag erzwingen. (Wenn Sie gcc verwenden, denke ich, ist es -msoft-float)
Längerfristig, wenn der Prozessor Ihres Ziels Hardware-Unterstützung für Gleitkommaoperationen bietet, möchten Sie im Allgemeinen eine Cross-Toolchain mit aktiviertem Hardware-Float erstellen oder finden, um die Geschwindigkeit zu erhöhen. Einige Prozessorfamilien haben Modellvarianten, einige mit und einige ohne Hardwareunterstützung. Wenn Sie beispielsweise nur sagen, dass Ihr Prozessor ein ARM ist, reicht es nicht aus, zu wissen, ob Sie Hardware-Gleitkomma-Unterstützung haben.
Die Berechnung kann entweder durch Gleitkomma-Hardware oder in Software erfolgen, die auf ganzzahliger Arithmetik basiert.
Dies in Hardware zu tun ist viel schneller, aber viele Mikrocontroller haben keine Gleitkomma-Hardware. In diesem Fall können Sie entweder die Verwendung von Gleitkommazahlen vermeiden (normalerweise die beste Option) oder sich auf eine Implementierung in Software verlassen, die Teil der C-Bibliothek ist.
In einigen Controller-Familien, z. B. ARM, ist die Gleitkomma-Hardware in einigen Modellen der Familie vorhanden, in anderen jedoch nicht. Daher unterstützt gcc für diese Familien beide. Ihr Problem scheint zu sein, dass Sie die beiden Optionen verwechselt haben.
Antworten:
Harte Schwimmer verwenden eine On-Chip-Gleitkommaeinheit. Soft Floats emulieren einen in Software. Der Unterschied ist die Geschwindigkeit. Es ist seltsam zu sehen, dass beide auf derselben Zielarchitektur verwendet werden, da der Chip entweder eine FPU hat oder nicht. Sie können Soft-Floating Point in GCC mit -msoft-float aktivieren. Möglicherweise möchten Sie Ihre libc neu kompilieren, um Hardware-Gleitkomma zu verwenden, wenn Sie es verwenden.
quelle
Es gibt drei Möglichkeiten, Gleitkomma-Arithmetik durchzuführen:
quelle
Genau genommen scheinen mir all diese Antworten falsch zu sein.
Das Debian VFP-Wiki enthält Informationen zu den drei Auswahlmöglichkeiten für
-mfloat-abi
:soft
- Das ist reine Softwaresoftfp
- Dies unterstützt eine Hardware-FPU, aber der ABI ist soft-kompatibel.hard
- Der ABI verwendet Float- oder VFP- Register.Der Linker (Loader) -Fehler liegt daran, dass Sie über eine gemeinsam genutzte Bibliothek verfügen, die Gleitkommawerte in Ganzzahlregistern übergibt. Sie können immer noch Ihren Code mit einem kompilieren
-mfpu=vfp
, etc , aber Sie sollten verwenden ,-mfloat-abi=softfp
so dass , wenn die libc einen Schwimmer muss es in einer Weise geleitet wird , die Bibliothek versteht.Der Linux-Kernel kann die Emulation der VFP-Anweisungen unterstützen. Offensichtlich ist es
-mfpu=none
für diesen Fall besser, mit zu kompilieren, und die Kompilierung lässt Code direkt generieren, anstatt sich auf eine Linux-Kernel-Emulation zu verlassen. Ich glaube jedoch nicht, dass der Fehler des OP tatsächlich mit diesem Problem zusammenhängt. Es ist getrennt und muss auch zusammen mit dem behandelt werden-mfloat-abi
.Die gemeinsam genutzte Armv5-Bibliothek mit ArmV7-CPU ist das Gegenteil von dieser. Die libc war hart schwebend, aber die Anwendung war nur weich . Es gibt einige Möglichkeiten, um das Problem zu umgehen, aber das Neukompilieren mit den richtigen Optionen ist immer am einfachsten.
Ein weiteres Problem besteht darin, dass der Linux-Kernel VFP-Tasks (oder einen beliebigen vorhandenen ARM-Gleitkomma) unterstützen muss, um die Register auf einem Kontextwechsel zu speichern / wiederherzustellen.
quelle
Es hört sich so an, als ob Ihre libc für Software-Gleitkommaoperationen erstellt wurde, während Ihre exe unter der Annahme der Hardwareunterstützung für Gleitkomma kompiliert wurde. Kurzfristig könnten Sie Soft Floats als Compiler-Flag erzwingen. (Wenn Sie gcc verwenden, denke ich, ist es -msoft-float)
Längerfristig, wenn der Prozessor Ihres Ziels Hardware-Unterstützung für Gleitkommaoperationen bietet, möchten Sie im Allgemeinen eine Cross-Toolchain mit aktiviertem Hardware-Float erstellen oder finden, um die Geschwindigkeit zu erhöhen. Einige Prozessorfamilien haben Modellvarianten, einige mit und einige ohne Hardwareunterstützung. Wenn Sie beispielsweise nur sagen, dass Ihr Prozessor ein ARM ist, reicht es nicht aus, zu wissen, ob Sie Hardware-Gleitkomma-Unterstützung haben.
quelle
Die Berechnung kann entweder durch Gleitkomma-Hardware oder in Software erfolgen, die auf ganzzahliger Arithmetik basiert.
Dies in Hardware zu tun ist viel schneller, aber viele Mikrocontroller haben keine Gleitkomma-Hardware. In diesem Fall können Sie entweder die Verwendung von Gleitkommazahlen vermeiden (normalerweise die beste Option) oder sich auf eine Implementierung in Software verlassen, die Teil der C-Bibliothek ist.
In einigen Controller-Familien, z. B. ARM, ist die Gleitkomma-Hardware in einigen Modellen der Familie vorhanden, in anderen jedoch nicht. Daher unterstützt gcc für diese Familien beide. Ihr Problem scheint zu sein, dass Sie die beiden Optionen verwechselt haben.
quelle