[C++] Gleitkomma- zu Ganzzahlen runden
- Schrompf
- Moderator
- Beiträge: 5401
- Registriert: 25.02.2009, 23:44
- Benutzertext: Lernt nur selten dazu
- Echter Name: Thomas
- Wohnort: Dresden
- Kontaktdaten:
Re: [C++] Gleitkomma- zu Ganzzahlen runden
Wow, will haben! Pack's in eine kleine Funktion und mach einen dicken Kommentar drumrum, dass das im Falle einer Portierung geändert werden muss, dann hast Du nach meiner Meinung ausreichend Portabilität erreicht :-) Man sollte sich bei all diesen Überlegungen halt auch mal vor Auge halten, wer denn am Ende den Source wirklich mal in die Hand bekommt und auf welchen Compilern/Systemen der dann übersetzt werden soll. Wenn man da ehrlich zu sich selbst ist, ist bei 90% der Leute die Antwort: ein Rechner. Nämlich der eigene. Von daher: Portabilität wird allgemein überbewertet.
In Deinem Fall ist die Sache wohl kniffliger, weil Du tatsächlich selbst die 64Bit-Variante brauchst. In dem Fall musst Du wirklich weitersuchen. Ich würde mich dagegen freuen, wenn Du einfach mal Deinen bisherigen 32Bit-Inline-ASM-Code posten könntest... zu ähh... Lernzwecken :-)
Bye, Thomas
In Deinem Fall ist die Sache wohl kniffliger, weil Du tatsächlich selbst die 64Bit-Variante brauchst. In dem Fall musst Du wirklich weitersuchen. Ich würde mich dagegen freuen, wenn Du einfach mal Deinen bisherigen 32Bit-Inline-ASM-Code posten könntest... zu ähh... Lernzwecken :-)
Bye, Thomas
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
- kimmi
- Moderator
- Beiträge: 1416
- Registriert: 26.02.2009, 09:42
- Echter Name: Kim Kulling
- Wohnort: Luebeck
- Kontaktdaten:
Re: [C++] Gleitkomma- zu Ganzzahlen runden
Zum Thema Portabilität: bei privaten Projekten stimme ich Schrompf voll zu.
Bei beruflich motivierten Projekten: Ich habe schon unzähliche Überstunden geschoben, weil jemand Portabilität auf die zu leichte Schulter genommen hat und ein Compilerwechsel von x.00x auf x.00x+1 unerklärbare Abstürze provozierte :) . Also bitte beruflich zumindest mehr als einmal drüber nachdenken, danke ;) . Eure Nachfolger werden es euch danken.
Und ja, ich weiß, gehörte nicht zum Thema.
Gruß Kimmi
Bei beruflich motivierten Projekten: Ich habe schon unzähliche Überstunden geschoben, weil jemand Portabilität auf die zu leichte Schulter genommen hat und ein Compilerwechsel von x.00x auf x.00x+1 unerklärbare Abstürze provozierte :) . Also bitte beruflich zumindest mehr als einmal drüber nachdenken, danke ;) . Eure Nachfolger werden es euch danken.
Und ja, ich weiß, gehörte nicht zum Thema.
Gruß Kimmi
- Schrompf
- Moderator
- Beiträge: 5401
- Registriert: 25.02.2009, 23:44
- Benutzertext: Lernt nur selten dazu
- Echter Name: Thomas
- Wohnort: Dresden
- Kontaktdaten:
Re: [C++] Gleitkomma- zu Ganzzahlen runden
Öhm... ich rede von Compile-Time-Fehlern, die die zu portierenden Funktionen auf einem anderen System werfen sollten. Fehler zur Laufzeit sind unbedingt zu vermeiden. Im einfachsten Fall packt man einfach ein Boost-StaticAssert in die entsprechende Funktion, um Compiler und Prozessorarchitektor zu verifizieren, für die der Inline-ASM gedacht ist.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
- kimmi
- Moderator
- Beiträge: 1416
- Registriert: 26.02.2009, 09:42
- Echter Name: Kim Kulling
- Wohnort: Luebeck
- Kontaktdaten:
Re: [C++] Gleitkomma- zu Ganzzahlen runden
Und ich rede von Laufzeitfehlern, die aufgrund einer schlecht portierten Funktion / Methode entstanden sind, da jemand leider keine StaticAsserts um besagte Stelle gebaut hat. Gerade beim Erben von Legacy-Code habe ich derartige Probleme schon oft miterleben dürfen ( bei Compilerwechsel, Systemwechsel, OS-Wechsel, auch gern mal Wetterwechsel ;) ). Nicht jeder geht da so bewußt ran wie Schrompf :(.
Gruß Kimmi
Gruß Kimmi
- Krishty
- Establishment
- Beiträge: 8422
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [C++] Gleitkomma- zu Ganzzahlen runden
Gern, hier ist er. Ich habe einfach mal Referenzen statt einem Rückgabewert benutzt, weil das für die Benchmarks wahrscheinlich vorteilhaft ist:Schrompf hat geschrieben:Ich würde mich dagegen freuen, wenn Du einfach mal Deinen bisherigen 32Bit-Inline-ASM-Code posten könntest... zu ähh... Lernzwecken :-)
Code: Alles auswählen
inline void RoundSingle(const float & p_Source, signed int & p_Dest) {
__asm fld p_Source
__asm mov edx, p_Dest
__asm FRNDINT
__asm fistp dword ptr [edx];
}The Code Project bietet einen guten Artikel mit Haufen von nützlichen Float-Utilities, dort habe ich auch die Funktion her (die gibt es aber im Netz an jeder Ecke).
- kimmi
- Moderator
- Beiträge: 1416
- Registriert: 26.02.2009, 09:42
- Echter Name: Kim Kulling
- Wohnort: Luebeck
- Kontaktdaten:
Re: [C++] Gleitkomma- zu Ganzzahlen runden
Da sag ich ebenfalls Danke! Und der Link beinhaltet einiges sehr interessantes Zeug.
Gruß Kimmi
Gruß Kimmi
- Krishty
- Establishment
- Beiträge: 8422
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [C++] Gleitkomma- zu Ganzzahlen runden
Ähm, eine Frage am Rande … ich habe ja nicht viel Assembler-Erfahrung …
Ich habe die Funktion jetzt so umgebaut, dass sie einen Rückgabewert hat (signed int RoundSingle(float p_Value)). Da die Funktion keine lokalen Variablen benötigt und keine großen Parameter handhabt, habe ich sie __declspec(naked) gemacht und die Aufrufmethode __fastcall gewählt.
Darum meine Frage an die Experten: Ist das akzeptabler Stil? Werden „nackte“ Funktionen auch von anderen Compilern als VCpp unterstützt? Habe ich irgendwelche Probleme zu erwarten?
Ich habe die Funktion jetzt so umgebaut, dass sie einen Rückgabewert hat (signed int RoundSingle(float p_Value)). Da die Funktion keine lokalen Variablen benötigt und keine großen Parameter handhabt, habe ich sie __declspec(naked) gemacht und die Aufrufmethode __fastcall gewählt.
Darum meine Frage an die Experten: Ist das akzeptabler Stil? Werden „nackte“ Funktionen auch von anderen Compilern als VCpp unterstützt? Habe ich irgendwelche Probleme zu erwarten?
- kimmi
- Moderator
- Beiträge: 1416
- Registriert: 26.02.2009, 09:42
- Echter Name: Kim Kulling
- Wohnort: Luebeck
- Kontaktdaten:
Re: [C++] Gleitkomma- zu Ganzzahlen runden
Wenn ich die Postings von der gcc-ML richtig verstanden habe, unterstützen die ein __attribute__((naked)) , welches aber nicht auf allen Plattformen unterstützt wird: http://www.mailinglistarchive.com/gcc-h ... 08166.html
Müsste man mal probieren bzw. auf jemanden warten, der das genauer weiß als ich :-).
Gruß Kimmi
Müsste man mal probieren bzw. auf jemanden warten, der das genauer weiß als ich :-).
Gruß Kimmi
- Krishty
- Establishment
- Beiträge: 8422
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [C++] Gleitkomma- zu Ganzzahlen runden
Stimmt, auf x86 bspw. ist es ungültig und wird es wohl auch immer bleiben. Ich sehe aber gerade, dass ich scheinbar kein naked mehr angeben muss, wenn ich die Funktion in einer externen Datei assembliere – was ich der x64-Kompatibilität wegen ja sowieso machen muss.
Momentan habe ich aber noch Probleme mit MASM, ich melde mich zurück, wenn es funktioniert.
Momentan habe ich aber noch Probleme mit MASM, ich melde mich zurück, wenn es funktioniert.
Re: [C++] Gleitkomma- zu Ganzzahlen runden
Wozu frndint in der Funktion? fistp allein rundet auch....
Re: [C++] Gleitkomma- zu Ganzzahlen runden
Oh, das wuerde mich sehr erstaunen, in welchen Faellen unterscheidet sich fistp von frndint im Rundungsverhalten?
- Krishty
- Establishment
- Beiträge: 8422
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [C++] Gleitkomma- zu Ganzzahlen runden
Laut dem Artikel käme bei 65535.5 das Ergebnis 0 statt 65536 raus, wenn man frndint nicht explizit voran stellte.
Das ist ein Bug im Pentium-Prozessor, genau wie diese leidige fdiv-Sache damals … eigentlich ewig her und man könnte es weglassen … nur weiß man ja nie, worauf ihr den Code ausführt.
Das ist ein Bug im Pentium-Prozessor, genau wie diese leidige fdiv-Sache damals … eigentlich ewig her und man könnte es weglassen … nur weiß man ja nie, worauf ihr den Code ausführt.
Re: [C++] Gleitkomma- zu Ganzzahlen runden
Wenn ich das richtig lese, kannst du das ignorieren, da du fuer das Auftreten eh den Wertebereich der Ziels ueberschreiten musst.
http://support.microsoft.com/kb/126455/en-us
http://support.microsoft.com/kb/126455/en-us
- Krishty
- Establishment
- Beiträge: 8422
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [C++] Gleitkomma- zu Ganzzahlen runden
So, kleines Update … ohne frndint hat sich die Performance nochmal fast verdoppelt, ich bin jetzt bei der 45-fachen Geschwindigkeit eines static_cast – danke, Jörg.
Mit dem Assembler-Code, der nun endlich nicht mehr inline-Assembler ist, sondern mit MASM assembliert und extern gelinkt wird, ist allerdings der GAU eingetreten: Er wird nicht geinlined. Die Performance ist damit um den Faktor 100 schlechter geworden und ist nun nurnoch halb so schnell wie ein static_cast.
Hat jemand ein gutes Tutorial darüber, wie man MASM-Kompilate richtig in Visual-C++-Projekte einbindet und optimiert? Ich habe mich da quasi blind reingetastet und ihr seht, was rauskommt …
Mit dem Assembler-Code, der nun endlich nicht mehr inline-Assembler ist, sondern mit MASM assembliert und extern gelinkt wird, ist allerdings der GAU eingetreten: Er wird nicht geinlined. Die Performance ist damit um den Faktor 100 schlechter geworden und ist nun nurnoch halb so schnell wie ein static_cast.
Hat jemand ein gutes Tutorial darüber, wie man MASM-Kompilate richtig in Visual-C++-Projekte einbindet und optimiert? Ich habe mich da quasi blind reingetastet und ihr seht, was rauskommt …
- Krishty
- Establishment
- Beiträge: 8422
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [C++] Gleitkomma- zu Ganzzahlen runden
Ich habe keinen Bock mehr … ich werde erstmal die SSE-Intrinsics nutzen … sind genauso schnell wie fistp aber x86- sowie x64-tauglich … CPUs ohne SSE sind eh zu langsam für meine Bedürfnisse und den winzigen Präzisionsunterschied gegenüber der FPU würde ich ja eh nicht messen können … Assembler ist nervtötend und wenn ich noch mehr Zeit auf das Thema verschwende, kriege ich garnichts mehr gebacken -.-
Daher meine vorläufige Lösung, falls ihr nichts daran auszusetzen habt:Ich danke euch für eure Hilfe, in dem Thread ist ja letztendlich doch ein Haufen von Wissen und interessanter Codefragmente über FPU, Bitshifterei mit Gleitkommazahlen und Assemblertrickserei zusammengekommen :)
Falls Interesse daran besteht, wie man komplette Assembler-Dateien zu Visual-C++-Projekten linkt, kann ich noch ein Tutorial drüber schreiben – jetzt weiß ich ja, wie es geht.
Daher meine vorläufige Lösung, falls ihr nichts daran auszusetzen habt:
Code: Alles auswählen
#include <intrin.h>
signed int RoundFloatToInt(const float & p_Value) {
return ::_mm_cvt_ss2si(::_mm_load_ss(&p_Value));
}
signed int TruncFloatToInt(const float & p_Value) {
return ::_mm_cvtt_ss2si(::_mm_load_ss(&p_Value));
}
signed int RoundDoubleToInt(const double & p_Value) {
return ::_mm_cvtsd_si32(::_mm_load_sd(&p_Value));
}
signed int TruncDoubleToInt(const double & p_Value) {
return ::_mm_cvttsd_si32(::_mm_load_sd(&p_Value));
}Falls Interesse daran besteht, wie man komplette Assembler-Dateien zu Visual-C++-Projekten linkt, kann ich noch ein Tutorial drüber schreiben – jetzt weiß ich ja, wie es geht.
- Krishty
- Establishment
- Beiträge: 8422
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [C++] Gleitkomma- zu Ganzzahlen runden
Dieser Sache scheint man niemals Herr werden zu können -.-
Ich brauche jetzt eine zur 64-Bit-Integer gerundete Gleitkommazahl (die SSE-Intrinsics sind also nicht mehr ausreichend), ich brauche sie unter x64 (also goodbye, Assembler) und ich brauche sie performant.
Ich habe im Verlauf des Threads ja schon festgestellt, dass es dafür keinen portablen Code zu geben scheint – falls hier aber doch nochmal jemand drüber stolpert (oder auch nur über ein halb-portables Intrinsic), sei er ausdrücklich darum gebeten, zu antworten …
Wahnwitz und Idiotie, dass es für jeden Müll Intrinsics und Optimierungen gibt, man aber gerade bei sowas auf einem 24× langsameren, kaum praktisch anwendbaren Umweg beharrt.
Ich brauche jetzt eine zur 64-Bit-Integer gerundete Gleitkommazahl (die SSE-Intrinsics sind also nicht mehr ausreichend), ich brauche sie unter x64 (also goodbye, Assembler) und ich brauche sie performant.
Ich habe im Verlauf des Threads ja schon festgestellt, dass es dafür keinen portablen Code zu geben scheint – falls hier aber doch nochmal jemand drüber stolpert (oder auch nur über ein halb-portables Intrinsic), sei er ausdrücklich darum gebeten, zu antworten …
Wahnwitz und Idiotie, dass es für jeden Müll Intrinsics und Optimierungen gibt, man aber gerade bei sowas auf einem 24× langsameren, kaum praktisch anwendbaren Umweg beharrt.