Wenn ich in einem C Programm double nutze, die FPU aber nur float unterstützt, profitiert der Code dann noch von der FPU oder ist sie in diesem Fall unnütz? Falls es eine Rolle spielt, soll sich die Frage auf den STM32F303 mit arm-gcc und newlib-nano beziehen. Das ist nämlich mein konkreter Fall.
Soweit ich weiss bringt sie dann nichts... Kann mich aber irren
Nein, die FPU müßte von sich aus schon double unterstützen. Auf der anderen Seite ist double auf M3/M4 Prozessoren schon sehr schnell, sodaß es keinen Grund gibt, auf double zu verzichten, wenn man es braucht.
Falls möglich, werden vom Compiler auch beim Rechnen mit Doubles Instructions für eine Single FPU erzeugt. Natürlich wird das nicht immer möglich sein.
P. S. schrieb: > Falls möglich, werden vom Compiler auch beim Rechnen mit Doubles > Instructions für eine Single FPU erzeugt. Dann zeige mal ein einziges Beispiel. Ich bin gespannt ;-)
Ganz klar: Jein! Ohne passende Bibliotheken, die die konkrete FPU unterstützen, wird das nichts. Nur Hardware ändern, ändert an den Datentypen nichts. Es ist aber nicht ausgeschlossen, dass eine FPU insgesamt, da auf mathematische Berechnungen getrimmt, den "alten" Job schneller macht.
Float und Double ist auf µC meist keine Sinnvolle Lösung. Der Vorteil liegt bei extrem Großer Dynamik was bei unbekannten Signalen oder unbekannten Operationen hilfreich ist. aber 12 Bit Analog oder 16Bit über CAN oder Zähler ist keine große Dynamik Auch weiß man i.f.R genau was zu rechnen ist. Festkomma ist fast immer die beste Lösung. Fließkomma oder Skalierung mit 10, 100 , 1000 ist immer ein guter Hinweis das der Entwickler die Sache nicht durch gerechnet hat. Sich mit Themen wie Auflösung, Toleranzen, Rundungen, Genauigkeit, Fehlerrechnung, Überläufe... nie Beschäftigt hat. Und das fällt einem irgendwann schmerzhaft auf die Füße.
Sebastian S. schrieb: > Es ist aber nicht ausgeschlossen Warum melden sich hier andauernd Leute, die noch nie mit einer FPU gearbeitet haben?
Stefanus F. schrieb: > Falls es eine Rolle spielt, soll sich die Frage auf den STM32F303 mit > arm-gcc und newlib-nano beziehen. Bei ARM Cortex-M4F müsste man mit den ABIs spielen (soft, softfp, hard). Mit der "hardware" float ABI könne man sich eine Handbremse einhandeln, denn dort werden auch Double Werte über die FPU an Funktionen übergeben (die anderen Fälle benutzen CPU Register). Kann die FPU keine Doubles, müssen die Werte erst wieder aus der FPU zurück an die CPU übertragen werden, was natürlich Zeit kostet. Müsste der OP aber selbst überprüfen (z.B. mit 'nem Timer) was für ihn am Schnellsten läuft.
Probiere es doch einfach aus. Ich meine mich zu erinnern, daß die double-Quadratwurzel sqrt() auf einem STM32F446 weniger Takte als auf einem STM32F103 benötigt, aber leider sind da meine Notizen lückenhaft. Pin toggeln ist etwas umständlich. Zyklenzähler macht mehr Spaß. http://embeddedb.blogspot.com/2013/10/how-to-count-cycles-on-arm-cortex-m.html
:
Bearbeitet durch User
Ich arbeite seit einigen Monaten an einem privaten Audio-DSP Projekt. Hardware STM32F407. Also mit FPU. Ich rechne Filter, Reverb-Algorithmen und Modelle in einer 96kHz (10.4µs) Task und beobachte die Rechenzeiten der einzelnen Blöcke immer mit. Zuerst habe ich wie ich es bisher kannte mit Festkommaoperation gearbeitet, bin dann aber auf float umgestiegen. Das war ein Geschwindigkeitsvorteil, weil float oft genauso schnell berechnet wurde wie int. Aber ich habe auf einige Skalierungen verzichten können. Aber wehe ich haben irgendwo ein y= x * 3.14159265359; stehen. Das fehlende f für float führt dazu, dass double verwendet wird. Dann geht die Rechenzeit eines Filters schnell mal um Faktor 10 nach oben.
Audio Phil schrieb: > Das > fehlende f für float führt dazu, ...daß der Compiler eine Warnung ausspuckt, wenn man ihn läßt.
Volle schrieb: > Float und Double ist auf µC meist keine Sinnvolle Lösung. Das gilt vielleicht für einen 8-Bitter. Stefanus redet von einem 32-Bitter mit FPU.
ich hab mich auf 32bit bezogen (8 Bit Rechner hab ich 1992 ausgemustert) Thema Auflösung und Rundung da meinen viele irrtümlich das sei bei Fließkomma besser und kümmern sich nicht darum.
Walter T. schrieb: > Audio Phil schrieb: >> Das >> fehlende f für float führt dazu, > > ...daß der Compiler eine Warnung ausspuckt, wenn man ihn läßt. ... oder es passiert überhaupt nichts aufregendes, weil man mit -fsingle-precision-constant kompiliert
Christopher J. schrieb: > Walter T. schrieb: >> Audio Phil schrieb: >>> Das >>> fehlende f für float führt dazu, >> >> ...daß der Compiler eine Warnung ausspuckt, wenn man ihn läßt. > > ... oder es passiert überhaupt nichts aufregendes, weil man mit > -fsingle-precision-constant kompiliert Diese primitive Lösung bei der double und float 32bit hat gibt es nur bei den C/C++-Compilern der 8bit PICs und 8bit AVRs.
:
Bearbeitet durch User
Die STMs können doubels problemlos auf der FPU berechnen. Wenn man Atollic o.ä. benutzt wird auch automatisch die entsprechende Bibliothek benutzt. Es gibt von ST einen Appnote dazu was wieviele Takte braucht. Ich meine Double braucht genau ddoopelt so lange wie singel. Wobei Addition Subtraktion Multiplikation und Cast einen bzw dann 2 Takte brauchen. Und Wurzel und dividieren 8 bzw. 16. Wenn es mehr Performance braucht geh zum H7 der hat eine DP FPU.
Wie ihr an der Frage korrekt erkannt habe, habe ich Fließkomma-Operationen auf Mikrocontrollern praktisch keine Erfahrung. Auf 8bit µC habe ich gelernt, weitgehend mit Integer Datentypen auszukommen. Nun habe ich aber inzwischen auch einige STM32F303 Board in der Bastelkiste. Die haben eine FPU und deswegen ist das Thema "Fließkomma-Arithmetik" wieder hoch gekommen. Float ist allerdings manhcmal zu ungenau, daher meine Frage. Wenn der Unterschied zu Double gering wäre, würde ich einfach immer double nehmen - so handhabe ich das im Job (Server Backend).
auf µC gilt Datentypen so klein wie möglich und so groß wie nötig aus Bequemlichkeit pauschal double zu verwenden geht nicht lange gut. Autofahren nur mit dem 5. Gang macht innerorts keinen Spass. Und damit komme ich wieder zum Thema das man genau wissen sollte was sman macht bezüglich Aufösung Genauigkeit...
Stefanus F. schrieb: > Wie ihr an der Frage korrekt erkannt habe, habe ich > Fließkomma-Operationen auf Mikrocontrollern praktisch keine Erfahrung. Dass du keine Ahnung hast brauchst du nicht ständig betonen. Weiß hier jeder.
Boris schrieb: > Dass du keine Ahnung hast brauchst du nicht ständig betonen. Weiß hier > jeder. Danke fürs Nachtreten. Das war sehr weise und hilfreich.
Helmut S. schrieb: > Christopher J. schrieb: >> Walter T. schrieb: >>> Audio Phil schrieb: >>>> Das >>>> fehlende f für float führt dazu, >>> >>> ...daß der Compiler eine Warnung ausspuckt, wenn man ihn läßt. >> >> ... oder es passiert überhaupt nichts aufregendes, weil man mit >> -fsingle-precision-constant kompiliert > > Diese primitive Lösung bei der double und float 32bit hat gibt es nur > bei den C/C++-Compilern der 8bit PICs und 8bit AVRs. -fsingle-precision-constant bewirkt eben nicht, dass double äquivalent zu float ist, sondern nur dass Konstanten (auch ohne angehängtes f) als float behandelt werden. Hier mal ein Beispiel: https://godbolt.org/z/CL6fiQ
Stefanus F. schrieb: > Auf 8bit µC habe ich gelernt, weitgehend mit Integer Datentypen > auszukommen. Das sind die alten Vorurteile aus den 70/80ern. Aber selbst der PET hat schon mit 40 Bit Fließkommazahlen gearbeitet. Seit AVR habe ich gelernt, wenn ich float brauche nehme ich float. Und wenn ich dort double brauche, dann nehme ich auch double. Was soll der Geiz? > Float ist allerdings > manchmal zu ungenau, daher meine Frage. Wenn der Unterschied zu Double > gering wäre, würde ich einfach immer double nehmen - so handhabe ich das > im Job (Server Backend). Nimm double, wenn Du double brauchst. Ausführungszeiten habe ich Dir ja oben verlinkt. Und wenn es doch noch schneller gehen soll und float ausreicht, aktiviere die FPU und rechne damit. Bezahlt ist das Teil ja schon ;-) Und wie oben auch erwähnt, gibt es die H7xx, die die Grundrechenarten beider Typen per Hardware rechnen. Klein und günstig STM32H730/750, wenn man nicht dem Flash-Wahn erlegen ist.
m.n. schrieb: > P. S. schrieb: >> Falls möglich, werden vom Compiler auch beim Rechnen mit Doubles >> Instructions für eine Single FPU erzeugt. > > Dann zeige mal ein einziges Beispiel. Ich bin gespannt ;-) Ein naheliegender Fall wären mathematische Funktionen, die ihr Ergebnis schrittweise approximieren (z.B. mittels Newtonverfahren), bis die gewünschte Genauigkeit erreicht ist. da könnte man die ersten Schritte mit float rechnen, auch wenn man später ein double-Ergebnis will. Inwiefern das tatsächlich gemacht wird, weiß ich allerdings nicht. SDCC unterstützt ja kein double und keine FPU.
Philipp Klaus K. schrieb: > da könnte man die ersten Schritte > mit float rechnen, auch wenn man später ein double-Ergebnis will. > > Inwiefern das tatsächlich gemacht wird, weiß ich allerdings nicht. Wer so programmiert, hat einen an der Waffel! Ein Programm soll ein Problem lösen und nicht neue Fallstricke schaffen. Wenn sich hier Leute melden, deren Programm angeblich zu langsam läuft, dann liegt das nicht an den verwendeten Datentypen, sondern an ungeschickter Programmierung oder noch schlimmer, an Funktionen wie delay_ms(100).
m.n. schrieb: > Philipp Klaus K. schrieb: >> da könnte man die ersten Schritte mit float rechnen, >> auch wenn man später ein double-Ergebnis will. >> >> Inwiefern das tatsächlich gemacht wird, weiß ich >> allerdings nicht. > > Wer so programmiert, hat einen an der Waffel! Nein: Der hat Ahnung von Numerik. Aber sei unbesorgt: Das trifft auf die allermeisten Programmierer nicht zu. Keine Gefahr.
Philipp Klaus K. schrieb: > Inwiefern das tatsächlich gemacht wird, weiß ich > allerdings nicht. Es gab mindestens einen Signalprozessor, der das unterstützt hat. Typ weiss ich nicht. Dort gab es eine schnelle "ungefähre" Division und einen Extrabefehl, um mittels Fixpunktiteration die restlichen Stellen zu beschaffen.
Stefanus F. schrieb: > Wenn ich in einem C Programm double nutze, die FPU aber nur float > unterstützt, profitiert der Code dann noch von der FPU oder ist sie in > diesem Fall unnütz? Soweit ich es kenne, gibt es keine unmittelbare Möglichkeit die 32-Bit IEEE FPU für Doubles zu nutzen. Grundsätzlich kann sie aber schon als Basis für Berechnungen höherer Genauigkeit dienen. Dies wird (wurde?) beim Supercomputing gemacht, bei Archtikturen die GPUs nutzen. Stichwort float-float operators. Z.B. https://hal.archives-ouvertes.fr/hal-00021443/document http://andrewthall.org/papers/df64_qf128.pdf
Egon D. schrieb: > Es gab mindestens einen Signalprozessor, der das > unterstützt hat. Typ weiss ich nicht. Dort gab es eine > schnelle "ungefähre" Division und einen Extrabefehl, > um mittels Fixpunktiteration die restlichen Stellen > zu beschaffen. mindestens, weiss ich nicht, ungefähr, ... Na das ist ja alles sehr konkret. Ein Spezialfall soll nun die Standardlösung für jede numerische Berechnung sein? Und das, wo viele F7xx und alle H7xx µCs von Hause aus schon double Berechnungen per Hardware bieten? Und es gibt nach andere Anbieter ... Ich sag nur: Bahlsen!
Wie in einem anderen Thread rausgefunden haben die F76x und F77x eine DFPU. Nur zur Präzision ;) Ansonsten sehe ich das nicht so, dass eine FPU doubles beschleunigen kann. Das ist ja nicht wie bei einem fixkomma add mit 64bit wo es reicht ein normales add und danach ein add with carry auszuführen. Selbst ein 64bit MUL geht mit 3 32Bit MULs und einer Abfrage. f32 und f64 sind komplett anders aufgebaut. Das f64 müsst man also erstmal entpacken, dann gucken obs beschleunigbar wäre und diesen Teil wieder nach f32 packen damits die FPU auch versteht. Da kann mans dann auch gleich direkt mit dem integer Teil der CPU rechnen. Im Disasm sieht der pack/entpack Teil der f64 lib viel größer aus als de eigentliche Rechenteil. Wie eine FPU addiert hab ich mal als pdf in den Anhang gepackt. Das sind ja auch eure Steuergelder ;)
m.n. schrieb: > Ein Spezialfall soll nun die Standardlösung für jede numerische > Berechnung sein? Hat doch keiner gesagt. Im Rahmen meiner fand ich diese Idee durchaus für passend, obwohl mir klar war, dass es nur ein Spezialfall ist.
Mw E. schrieb: > Das ist ja nicht wie bei einem fixkomma add mit 64bit wo es reicht ein > normales add und danach ein add with carry auszuführen. > Selbst ein 64bit MUL geht mit 3 32Bit MULs und einer Abfrage. Das war mein Gedanke dahinter. Wenn man große Integer Operationen in kleine zerlegen kann, dann vermutlich auch mit Fließkommazahlen. Nur war mir halt nicht klar, ob sich dann die Nutzung der kleinen FPU überhaupt noch lohnt.
Stefanus F. schrieb: > Im Rahmen meiner fand ich diese Idee durchaus > für passend, obwohl mir klar war, dass es nur ein Spezialfall ist. Dann sag doch, was genau Du rechnen willst. Deine Frage war allgemeiner Natur und nichts Spezielles und erst recht nichts Zeitkritisches.
m.n. schrieb: > Dann sag doch, was genau Du rechnen willst. Kann ich leider nicht. In diesem Thread geht es mir nicht um eine Lösung für ein konkretes Problem, sondern darum, den Sachverhalt zu verstehen. Bisher bin ich immer mit Integer ausgekommen. Doch in Zukunft, wenn float oder double "billig" ist, werde ich mir wohl einige Klimmzüge zur Nutzung von Integer sparen. Für mich ist die eigentliche Frage eher: Nehme ich dann float oder double? Da ich nun verstehe, dass double nicht von der kleinen FPU profitiert, kommt also wohl nur float in Frage. Wo das nicht genügt würde ich dann doch wieder lange Integer verwenden. > Deine Frage war allgemeiner Natur und nichts Spezielles > und erst recht nichts Zeitkritisches. Ja stimmt. Die Idee, sich per Float an einen Wert anzunähern und dann erst genauer weiter zu rechnen ist für mich aber auch interessant. Denn einen Annäherungs-Algorithmus hatte ich mal auf einem ATmega16 gebraucht. In diesem Fall ging es darum, einen fahrenden Roboter sanft zu bremsen, wofür ich fortlaufend den verbleibenden Bremsweg schätzen musste. Da war die sqrt() Funktion zu schwergewichtig. Mit FPU würde ich jedoch nochmal sqrt() versuchen, weil es einfacher wäre. Deswegen interessiert mich der Aspekt schon, den Egon da ansprach.
Dann nimm eben ein integer sqrt ;) Hab ich bei meinem Wirkleistungsmessgerät genutzt um bei 125kS/s RMS zu berechnen für I und U.
Stefanus F. schrieb: > Da ich nun verstehe, dass double nicht von der kleinen FPU profitiert, > kommt also wohl nur float in Frage. Wo das nicht genügt würde ich dann > doch wieder lange Integer verwenden. Gut, dann bleib bei Deinen Vorurteilen, daß Fließkommaverarbeitung langsam und damit böse ist. Es ist ja nichts Neues, daß u.a. float/double bei vielen µC Anwendern Einnässen auslöst.
Stefanus F. schrieb: > Da ich nun verstehe, dass double nicht von der kleinen FPU profitiert, > kommt also wohl nur float in Frage. m.n. schrieb: > Gut, dann bleib bei Deinen Vorurteilen, daß > Fließkommaverarbeitung langsam und damit böse ist. Ich habe kein Vorurteil. Wie kommst du überhaupt auf den Schluss, dass "kommt wohl nur float in Frage" für mich bedeutet, dass "Fließkommaverarbeitung langsam und damit böse" sei? Ich habe doch gerade erst angekündigt, float benutzen zu wollen! Tschuldigung, aber dein Schluss entbehrt jeder Logik.
13.10.2019 11:34 - 12.10.2019 10:57 = 1 Tag und 37 Minuten. In 5 Minuten hast Du das doch selbst ausprobiert. Einmal mit, einmal ohne FPU kompiliert.
Für mich ist ein Programm optimal wenn es gut zu verstehen ist und damit wartbar ist, das ist mir um Längen wichtiger als kürzest mögliche Ausführungszeit. Also erstmal einfach und verständlich programmiert, dann wenn nötig optimieren und nicht gleich alles dem Performancegott opfern. Fehler kann man mit jedem Datentypen machen, alle haben ihre Tücken. Wer mir sagt das er als Anfänger da nie drauf reingefallen ist dem glaube ich nicht. Bei Integer kann man auch ruck zuck Überläufe erzeugen, z.B. eine lange Berechnung und das Zwischenergebnis wird zu groß. In C/C++ wird sowas nicht abgefangen und ein vermeintlich funktionierendes Programm macht irgendwann Blödsinn. Float skaliert sich durch die Normierung automatisch, aber bei Addition kleiner Werte auf Große muss man genauso aufpassen. Schönes Beispiel ist die Berechnung der Standardabweichung wo durch Addition der Quadrate schnell große Summen entstehen. Trotzdem reichen floats in vielen Berechnungen die man mit µC macht. Hier war mal PID Berechnung das Thema, ich habe es auf dem STM32F407 gemessen und die float Rechnung brauchte 0,54 µs. Da lohnt es sich wohl kaum das mit Integer und Klimmzügen optimieren zu wollen. Nur bei den M0 muss man gut aufpassen, eine Mul wie
1 | x *= 10.0; |
erzeugt sofort vielmehr Code wenn double ins Spiel kommen. Bei der Umsetzung von AVR-Arduino Libs läuft man da schnell rein weil die AVR Programmierer den Unterschied nicht beachten mussten.
Mal wieder ein typisch sinnlos zerpflückter Text. Die Frage war: Bewirkt beim Cortex M4F die FPU eine Beschleunigung. Ich halte die Frage für halbwegs berechtigt. Nicht komplett berechtigt, weil ich bei einem Quelltext, der 64-Bit-Float benutzt, sicherlich auch an anderen Stellen 32-Bit-Float benutze, und schon allein deswegen die FPU-Unterstützung auf jeden Fall einschalte. Also wird der Vergleich wohl kaum M4 gegen M4F beinhalten. Aber die Frage impliziert ja auch: "Wieviel ist ein M4 schneller als ein M3 bei double-Berechnungen?" Und das ist durchaus interessant.
Audio Phil schrieb: > In 5 Minuten hast Du das doch selbst ausprobiert. Einmal mit, einmal > ohne FPU kompiliert. Da hast du wohl Recht. Ich hätte es auch ausprobieren können. Allerdings neige ich dazu, das Testergebnis für allgemein gültig zu halten. Solche Diskussionen hier helfen mir, das Thema differenzierter zu betrachten.
Wieso schreibt Ihr nicht einfach einen Benchmark und stellt den hier rein?
chris schrieb: > Wieso schreibt Ihr nicht einfach einen Benchmark und stellt den > hier rein? Habe ich doch gerade erst erklärt: Stefanus F. schrieb: > neige ich dazu, das Testergebnis für allgemein gültig zu halten. Solche > Diskussionen hier helfen mir, das Thema differenzierter zu betrachten.
Schnauze schrieb: > Womit wir wieder bei der Aussage von Boris wären. Gib mal etwas intelligentes oder wenigstens hilfreiches von Dir!
Volle schrieb: > Festkomma ist fast immer die beste Lösung. Prust. Nur weil die ADCs und DACs 16bittig sind, heißt das noch lange nicht, daß in der Rechnung keine größere Dynamik benötigt wird. Ich hatte z.B. bei einer PID-Regelung ständig mit Rundungsfehlern und Überläufen zu kämpfen. Nach der Umstellung auf float lief sie perfekt.
Als ich mein Wirkleistungsmessgerät das erste mal ans Netz gehangen habe wurden die ADC Werte auch so groß, dass mir mein Fixkomma um die Ohren geflogen ist. Nunja, jetzt sinds eben uint64_t ;) (I/U RMS Berechnung über Aufsummierung) Da der M3 keine FPU hat bleibt das auch erstmal so.
Eine single precision FPU nützt für double precision leider nichts. Berechnungen mit double erzeugen trotzdem Aufrufe in die EABI und werden durch die CPU emuliert. Je nachdem was man tun möchte kann man aber mehr Präzision aus einer single precision FPU herausholen, indem man mehrere Variablen nutzt. Als Beispiel für Addition das Kahan/Neumeier Verfahren: https://en.wikipedia.org/wiki/Kahan_summation_algorithm Mit ähnlichen Tricks kann man sich double oft sparen. Im Vergleich zur Software Emulation von double bietet die FPU Nutzung dann erhebliche Geschwindigkeitsvorteile.
Es gibt tatsächlich noch eine Möglichkeit, double als Summe zweier float effizient zu implementieren. Man erhält dabei zwar keinen IEEE double (selbst wenn man einen IEEE float hat), aber einen double, der dem C-Standard (siehe Abschnitt 5.2.4.2.2 im aktuellen ISO C17) entspricht. Damit erhält man etwa die Genauigkeit eines "normalen" double, aber gwinnt ist bezüglich der größtmöglichen und kelinstmöglichen darstellbaren Zahlen kaum etwas (man hat also etwa die Mantisse wie bei einem double, aber der Wertebereich des Exponenten bleibt etwa wie bei einem float). Ob dies in aktuellen Compilern verwendet wird, weiß ich nicht. Verbreitet ist oder war aber die analoge Implementierung eines 128-bit long double auf Hardware, die nur 64-bit double unterstützt. Siehe: T.J. Dekker, "A floating-point technique for extending the available precision" in Numerische Mathematik, Band 18, Heft 3, Seiten 224, 242, Springer, 1971.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.