Autor |
Beitrag |
Brainiac
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Sa 20.05.06 23:46
Hi!
Da ich demnächst ja doch noch mal meine ganzen OpenGL Komponenten veröffentlichen wollte, bin ich gerade dabei, sie etwas aufzupolieren. Wichtig wäre mir natürlich eine SSE Optimierung, weil die ja heutzutage praktisch schon Standard ist.
Was mir vorallem mal fehlt wäre eine Matrix-Matrix Multiplikation.
Eigentlich muss es ja sowas haufenweise geben. Trotzdem habe ich aber bei Google nix passendes finden können...
Problem eigentlich ganz klassisch. Zwei 4x4 Matrizen in Spaltenform...
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
| TGLVectorf4 = array[0..3] of TGLFloat; TGLMatrixf4 = array[0..3] of TGLVectorf4;
Procedure MatrixMultiply(const M1,M2:TGLMatrixf4; out Result:TGLMatrixf4); begin Result[0,0]:=M1[0,0]*M2[0,0]+M1[1,0]*M2[0,1]+M1[2,0]*M2[0,2]+M1[3,0]*M2[0,3]; Result[0,1]:=M1[0,1]*M2[0,0]+M1[1,1]*M2[0,1]+M1[2,1]*M2[0,2]+M1[3,1]*M2[0,3]; Result[0,2]:=M1[0,2]*M2[0,0]+M1[1,2]*M2[0,1]+M1[2,2]*M2[0,2]+M1[3,2]*M2[0,3]; Result[0,3]:=M1[0,3]*M2[0,0]+M1[1,3]*M2[0,1]+M1[2,3]*M2[0,2]+M1[3,3]*M2[0,3]; Result[1,0]:=M1[0,0]*M2[1,0]+M1[1,0]*M2[1,1]+M1[2,0]*M2[1,2]+M1[3,0]*M2[1,3]; Result[1,1]:=M1[0,1]*M2[1,0]+M1[1,1]*M2[1,1]+M1[2,1]*M2[1,2]+M1[3,1]*M2[1,3]; Result[1,2]:=M1[0,2]*M2[1,0]+M1[1,2]*M2[1,1]+M1[2,2]*M2[1,2]+M1[3,2]*M2[1,3]; Result[1,3]:=M1[0,3]*M2[1,0]+M1[1,3]*M2[1,1]+M1[2,3]*M2[1,2]+M1[3,3]*M2[1,3]; Result[2,0]:=M1[0,0]*M2[2,0]+M1[1,0]*M2[2,1]+M1[2,0]*M2[2,2]+M1[3,0]*M2[2,3]; Result[2,1]:=M1[0,1]*M2[2,0]+M1[1,1]*M2[2,1]+M1[2,1]*M2[2,2]+M1[3,1]*M2[2,3]; Result[2,2]:=M1[0,2]*M2[2,0]+M1[1,2]*M2[2,1]+M1[2,2]*M2[2,2]+M1[3,2]*M2[2,3]; Result[2,3]:=M1[0,3]*M2[2,0]+M1[1,3]*M2[2,1]+M1[2,3]*M2[2,2]+M1[3,3]*M2[2,3]; Result[3,0]:=M1[0,0]*M2[3,0]+M1[1,0]*M2[3,1]+M1[2,0]*M2[3,2]+M1[3,0]*M2[3,3]; Result[3,1]:=M1[0,1]*M2[3,0]+M1[1,1]*M2[3,1]+M1[2,1]*M2[3,2]+M1[3,1]*M2[3,3]; Result[3,2]:=M1[0,2]*M2[3,0]+M1[1,2]*M2[3,1]+M1[2,2]*M2[3,2]+M1[3,2]*M2[3,3]; Result[3,3]:=M1[0,3]*M2[3,0]+M1[1,3]*M2[3,1]+M1[2,3]*M2[3,2]+M1[3,3]*M2[3,3]; end; |
So sieht das als normaler Delphicode aus. Ich bräuchte jetzt halt den Assembler-Code der SSE nutzt.
Für Vektoren und ähnliches bekomme ich das auch selber hin, aber das hier wird mir etwas zu kompliziert.
Wenn irgendwo jemand passenden Code gesehen hat (kann auch innerhalb C oder Java sein, ist ja alles asm), dann wäre es toll, wenn er es kurz posten könnte.
THX!
Gruß
Brainiac
|
|
Spaceguide
Beiträge: 552
(D3/D7/D8) Prof.
|
Verfasst: So 21.05.06 13:03
|
|
Brainiac
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Sa 27.05.06 11:41
Also ich hab's jetzt doch einfach selbst geschrieben (und gerade mal 15 Minuten gebraucht).
Eigentlich ist das ganze ja doch recht einfach wenn man sich es genau ansieht.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76:
| procedure MatrixMultiplySSE(const M1,M2:TGLMatrixf4; out Result:TGLMatrixf4); asm movups xmm4, [eax] movups xmm5, [eax+$10] movups xmm6, [eax+$20] movups xmm7, [eax+$30] movss xmm0, [edx] shufps xmm0, xmm0, $00 mulps xmm0, xmm4 movss xmm1, [edx+$04] shufps xmm1, xmm1, $00 mulps xmm1, xmm5 addps xmm0, xmm1 movss xmm1, [edx+$08] shufps xmm1, xmm1, $00 mulps xmm1, xmm6 addps xmm0, xmm1 movss xmm1, [edx+$0c] shufps xmm1, xmm1, $00 mulps xmm1, xmm7 addps xmm0, xmm1 movups [ecx], xmm0 movss xmm0, [edx+$10] shufps xmm0, xmm0, $00 mulps xmm0, xmm4 movss xmm1, [edx+$14] shufps xmm1, xmm1, $00 mulps xmm1, xmm5 addps xmm0, xmm1 movss xmm1, [edx+$18] shufps xmm1, xmm1, $00 mulps xmm1, xmm6 addps xmm0, xmm1 movss xmm1, [edx+$1c] shufps xmm1, xmm1, $00 mulps xmm1, xmm7 addps xmm0, xmm1 movups [ecx+$10], xmm0 movss xmm0, [edx+$20] shufps xmm0, xmm0, $00 mulps xmm0, xmm4 movss xmm1, [edx+$24] shufps xmm1, xmm1, $00 mulps xmm1, xmm5 addps xmm0, xmm1 movss xmm1, [edx+$28] shufps xmm1, xmm1, $00 mulps xmm1, xmm6 addps xmm0, xmm1 movss xmm1, [edx+$2c] shufps xmm1, xmm1, $00 mulps xmm1, xmm7 addps xmm0, xmm1 movups [ecx+$20], xmm0 movss xmm0, [edx+$30] shufps xmm0, xmm0, $00 mulps xmm0, xmm4 movss xmm1, [edx+$34] shufps xmm1, xmm1, $00 mulps xmm1, xmm5 addps xmm0, xmm1 movss xmm1, [edx+$38] shufps xmm1, xmm1, $00 mulps xmm1, xmm6 addps xmm0, xmm1 movss xmm1, [edx+$3c] shufps xmm1, xmm1, $00 mulps xmm1, xmm7 addps xmm0, xmm1 movups [ecx+$30], xmm0 end; |
Trotzdem danke für den Link.
Auf Prefetching hab ich jetzt mal verzichtet. Ich hab zum testen 1000000x willkürliche Matrizen aus einem Array miteinander multiplizieren lassen und die Zeit in Takten gestoppt.
Mit prefetching hab ich dabei eher eine negative Auswirkung feststellen können.
Scheinbar weiß mein P4 wohl bei solch einfachen aufgaben am besten selbst, was er als nächstes braucht.
Was noch performance bringen könnte, wäre wenn die Matrizen 'aligned' im Speicher liegen würden, also die Adressen durch 64 teilbar wären. Weiß jemand, wie man Delphi dazu bringen kann, sowas korrekt anzulegen???
|
|
Horst_H
Beiträge: 1652
Erhaltene Danke: 243
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: Sa 27.05.06 13:16
Hallo,
reicht nicht teilbar durch 16?
Mit dem FastMemoryManager4 soll dies moeglich sein, bei grossen(>2.5 k) ist dies immer der Fall.
Delphi-Quelltext
in FastMM4Options.inc
Zitat: |
{---------------------------Miscellaneous Options-----------------------------}
{Enable this define to align all blocks on 16 byte boundaries so aligned SSE
instructions can be used safely. If this option is disabled then some of the
smallest block sizes will be 8-byte aligned instead which may result in a
reduction in memory usage.
Medium and large blocks are always 16-byte aligned irrespective of this setting.}
{.$define Align16Bytes} |
sourceforge.net/proj....php?group_id=130631
Gruss Horst
|
|
|