sin/cos in/um atan2 anders ausdruecken/optimieren?
-
SeppJ schrieb:
Viele Rechnenwerke können Sinus und Cosinus gemeinsam berechnen. Da besteht noch Handoptimierungspotential, sofern dein Compiler diese Optimierung nicht schafft.
es gibt den alten x86 FPU FSINCOS - der ist aber sehr langsam verglichen mit den neueren SSE2(+) Implementationen, und der Microsoft-Kompiler fasst sin/cos nicht zusammen weil ja der 1. Aufruf errno setzen könnte - gcc ruft eine zusammengefasste routine auf, clang kann man da mit fast-math-sub-optionen nachhelfen
ich habe auch schon versuche mit boost.SIMD gemacht - war aber viel langsamer - werde da aber noch die Autor kontaktieren
SeppJ schrieb:
Ich weis ja nun nicht wo dein c herkommt.
Das ist direkt eine Achsenposition - die kann alles von double min/max annehmen (nach meinem bisherigen Wissen)
-
ich verstehe auch überhaupt nicht warum diese Proposal zum hinzufuegen von std::sincos (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0081r0.pdf) in der Luft haengen geblieben ist - alle: egal ob Intel, Microsoft, clang, gcc, libc etc... jeder hat n Varianten (single/double/gpu/x86/x64(sse...)) - nur keine davon ist per Standard erreichbar
oder dieser Hẹckmeck mit den math.h Routinen die errno setzen - und Optimierung verhindern - teilweise machen es die gcc-Routinen, manche nicht, clang hat wieder andere Builtins/Optimierungen - auf einer anderen Platform/Stdlib wieder total anders und, und, und
ich hatte mal Kontakt mit einem der clang-cl Entwickler und der hat nur gemeint man soll den ganzen Müll in math.h mit komplett neuen Funktionen in einem neuen Namespace überlagern und die alten Zöpfe langsam abschneidbar machen
- irgendwie stört sich niemand so richtig am dem Ist-Zustand - nur die Leute die damit kämpfen - und die sind scheinbar nicht laut genug
-
oder floating-Point(0) Optimierung nichts als #pragmas - sondern nur von aussen per --fast-math-optionen, kaum bis nichts bei Microsoft, einfach ein sehr unordentliches Süppchen da draussen
-
hatte kurz Zugriff auf einen Dual Linux/Windows Rechner und einen sincos-Vergleich gemacht
Windows 7 x64, VS2017, x64/Release: 13,7 sek (kein sincos vorhanden)
Standardsettings fuer ReleaseLinux Ubuntu 17.04 x64, gcc 6.3, x64/Release: 10.4 sek (mit sincos per default)
g++ -O2
mit -march=native ist es langsamer geworden so 12.5 sek?
-
so jetzt bin ich mal wieder dazu gekommen alles zu testen
dein tip mit remainder und atan2 hat für einen Fall wunderbar funktioniert
double v_atan2 = atan2(cos_c, sin_c) / 2.0; double v_remainder = -remainder(c - M_PI / 2.0, M_PI * 2.0) / 2.0;
aber für einen anderen Fall ist das Ergebnis nicht immer richtig
double v_atan2 = atan2(-cos_c, -sin_c) / 2.0; double v_remainder = remainder(c - M_PI / 2.0, M_PI*2.0) / 2.0;
kannst du mir nochmal erklären wie das mit dem reminder funktioniert damit
ich das korrigieren kann
-
Gast3 schrieb:
aber für einen anderen Fall ist das Ergebnis nicht immer richtig
double v_atan2 = atan2(-cos_c, -sin_c) / 2.0; double v_remainder = remainder(c - M_PI / 2.0, M_PI*2.0) / 2.0;
Deine Umformung ist inkorrekt. -cos_c und -sin_c entsteht, indem du c um π verschiebst.
double v_remainder = remainder(-M_PI / 2.0 - c, M_PI*2.0) / 2.0;
ist eine Möglichkeit.
Bezgl.längerer Laufzeit mit -march=native (bzw. -mavx) ggf. https://www.c-plusplus.net/forum/344147 beachten.
-
Deine Umformung ist inkorrekt. -cos_c und -sin_c entsteht, indem du c um π verschiebst.
Danke jetzt funktioniert es richtig - und ist auch gleich noch ein bisschen schneller geworden
die Nutzung von remainder an dieser Stelle sollte auch die Präzision(weniger Rundungsfehler usw.) gegenüber atan2/sin/cos erhöhen oder sehe ich das falsch?
sollte ich die Kinematik-Berechnung doch noch mal komplett frisch betrachten wird das eine oder andere aus den Diskussionen hier bestimmt mit einfliessen
Danke
-
jetzt habe die ganze Kinematik noch mal durchgearbeitet und hab das ganze drastisch reduziert (kein If/Else, nur noch eine Rechnung)
für mein gefordertes Ergebnis brauche ich jetzt nur noch:
(
x * sin(c) + y * cos(c),
z * sin(a) - cos(a) * (x * cos(c) - y * sin(c)),
x * sin(a) * cos(c) - y * sin(a) * sin(c) + z * cos(a)
) + offsets()einfacher geht wohl nicht mehr und hat die Berechnung nochmal um Faktor 2 beschleunigt
jetzt sind die einzigen Zeitfresse sin und cos
hat jemand vielleicht einen Tip ob es performantere Implementationen gibt
die nicht total weit weg sind von der Präzision der Standardimplementationen?habe mir folgende angeschaut:
http://gruntthepeon.free.fr/ssemath/ (original)
https://github.com/RJVB/sse_mathfun (erweitert um SS3 und SSE4)
eine abgewandelte Form von ssemath wird auch in Eigen verwendet:
Eigen/src/Core/arch/SSE/MathFunctions.h
Eigen/src/Core/arch/AVX/MathFunctions.h
dann soll es noch was von Intel oder AMD gebenbtw: der x86 FSINCOS Befehl ist nicht schneller und nicht das was ich suche, nur eine SSE2+ Implementation kann da noch helfen - die eingebauten sin/cos sind schon SSE2+
Erfahrungswerte?
-
und Boost.SIMD
ssemath ist teilweise sehr ungenau und Boost.SIMD ist ein paar Sekunden langsamer
-
dann gibts es noch sincos Implementationen in
Intel Integrated Performance Primitives (IPP)
Intel Math Kernel Library (MKL)
AMD Math Library (LibM)
AMD Core Math Library (ACML)
-
ganz vergessen zu schreiben:
die Sin+Cos Berechnungen brauche ca. 60-70% der Zeit (bei 70Mio Testläufen)