amd-pipeline
-
hallo,
ich hab mal einbichen in den datenblättern meines prozessors geschmökert und gelesen, dass der amd-model8-prozessor 3 integer-pipelines, 3 adressberechnungs-pilelines und 3 floatingpoint-pipelines hat. also insgesammt 9.
so .. jetzt zum kern meiner fragemovq mm0, [%eax] pfmul mm0, [%ebx] movq [%eax], mm0
das kurze codestück da oben wird "einemilliardemal" asgeführt (auf einem specherbereich dessen offset in ebx/eax liegt und nach jeder ausführung entsprechend erhöht wird).
lohnt es sich das codestück etwas "auszurollen", um eine optimalere pipelineausnutzung zu erreichen?
da die von amd darauf wertlegen dass es sich um 3x3 pipelines handelt, würde ich dann quasi erst 3 movq befehle anstossen, dann 3 floatingpoint operationen und dann wieder 3 movq...
dummerweise habe ich (so schön sich das auch anhört) ein schlechtes gefühl bei der sache.. alsob das nicht stimmen würde was ich mir da zusammengelegt habe
wenn sich jemand in der materie auskennt würde ich mich über eine antwort freuen.gruss
eviluser
-
Kennst du den AMD CodeAnalyst? Damit kannst du solchen Code simulieren und die Perfomance (Pipelineauslastung u.a.) analysieren.
CodeAnalyst gibt es kostenlos auf der AMD-Seite.
-
Im zweifelsfall hilft nur ausprobieren.
der hauptgrund, in diesem falle die schleife etwas auszurollen, würde darin liegen, die befehlsanzahl pro zyklus zu senken. mal ausgehend von der grundform:mov eax, ... mov ebx, ... add eax, 1000 add ebx, 1000 mov edx, 1000000000 / 1000 _loop2:mov ecx, -1000 ; sicher ist der speicherblock nicht 4GB groß _loop: movq mm0, [ eax + ecx * 8 ] inc ecx pfmul mm0, [ ebx + ecx * 8 ] movq [ eax + ecx ], mm0 jnz _loop dec edx jnz _loop2
hast du hier 5 befehle im inneren zyklus
wenn wir das jetzt einmal ausrollen:_loop2:mov ecx, -1000 _loop: movq mm0, [ eax + ecx * 8 ] add ecx, 2 pfmul mm0, [ ebx + ecx * 8 ] movq mm1, [ eax + ecx * 8 + 8 ] pfmul mm1, [ ebx + ecx * 8 + 8 ] movq [ eax + ecx * 8 ], mm0 movq [ eax + ecx * 8 + 8 ], mm1 jnz _loop dec edx jnz _loop2
sind es offenbar nur noch 4 pro zyklus, da einmal inc und jmp eingespart wurden,
ein weiteres denkbares problem ist im nicht ausgerollten fall, dass der storebefehl movq [ .. ], mm0 evtl. das laden im nächsten zyklus verzögert, wenn beide befehle auf dieselbe cacheline wirken. ausserdem kann dieser storebefehl ja ohnehin nicht gleich ausgeführt werden, da erst auf das ergebnis von pfmul gewartet werden muss
man könnte noch versuchen, das ganze noch einmal um den faktor 2 auszurollen, mehr lohnt dann wahrscheinlich nicht mehr
-
im allg. sollte man versuchen, pipelines jeden typs beschäftigt zu halten (insbes. mit fpu), als die existenz mehrerer gleichartiger pipes auszunutzen: also z.b. mov,add,mul abwechseln - wenn du mov und mul und add jeweils für sich gruppierst, sind die anderen pipes ja nicht beschäftigt. alle 9 gleichzeitig auszunutzen wird dir sowieso nicht gelingen, im zweifelsfall wartest du nur auf den speicher