dot hat geschrieben:Krishty hat geschrieben:Dir Rückgabe ist die Pest; Visual C++ verschüttet die Rückgabewerte dauernd auf den Stapelspeicher. Zwar werden die Register drei Mal so effizient ausgenutzt (habe leider nur X, Y, & Z), aber dafür bewirkt das Shuffling dermaßen viele temporäre Werte, dass der Registerdruck dennoch steigt. Irre. Da weiß man sofort, warum andere Befehlssätze hunderte Register haben.
Auch mit
__vectorcall?
Habe ich garnicht erst versucht, weil sich das vor allem
auf sowieso geinlinete Funktionen bezog. Es findet kein Funktionsaufruf mehr statt, aber trotzdem sind da sechs
movaps zum und vom Stapel. WTF.
DerAlbi hat geschrieben:Aber da war von vorn herein auch alles darauf ausgelegt parallelisiert zu werden. Datenlayout ist da halt wichtig. wenn man Anfängt aufnicht-ausgerichteten adressen zu arbeiten oder die floats erst zusammensucht, um sie parallel zu verarbeiten... näääh geht nich. Aber gut. Als RISC-Mensch... bei mir ist das alles deterministischer :-D
Auf das Layout habe ich quasi keinen Einfluss mehr, das ist verlorener Posten. War halt nicht mein Design :( Und ein Neu-Design lohnt sich erst, wenn Visual C++ irgendwann mal Address Of Label implementiert.
Ich habe hier eine Stelle, wo ich die Größe des Arbeitssatzes (also RAM-Durchsatz) gegen Layout abwägen muss: Ein Batzen Vertices liegt in 16-Bit-
shorts vor. SSE 2 kriegt es um’s Verderben nicht auf die Kette, die effizient zu
float zu konvertieren. Alles, was mit 16-Bit-Zahlen zu tun hat, läuft nur noch über die MMX-Register, die in x64 sowieso nicht mehr ansprechbar sind. Vier
ints zu vier
floats konvertieren? Als ob – den Befehl gibt es nur als skalar oder als
2er-Vektor (!). Ach die schönen Legacy-Befehle. Und wenn ich alles mit 32-Bit-
ints aufziehe, pumpe ich in der innersten Schleife doppelt so viele Daten durch die CPU. Ganz zu schweigen davon, dass ich dann immernoch zwei Loads pro Element brauche, weil es ja keine 96-Bit-Operationen gibt. WTF. Als ich anfing, zwei 16-Bit-Zahlen im 64-Bit-Allzweckregister aufzupusten um das durch den Speicher in zwei
floats der SIMD-Einheiten zu aliasen, habe ich hingeschmissen, weil der Scheiß ja Endian-abhängig ist und ich die Stelle
niemals wieder finde wenn ich mal für ARM kompiliere. Bah. Und über die Umwege wär’s dann sowieso lahmer gewesen als drei skalare Konvertierungen, die zwar hintereinander laufen, aber zumindest direkt durch Register, mit Daten, die halb so viel RAM schlucken.