Wird der Compiler das optimieren?
-
Doppelte Derefernzierung sollten im Optimizer behandelt werden - aber ohne Gewähr!
Wenn du es wissen willst anstelle vom glauben musst du wohl bisschen Assembler lernen

-
Ich denke nicht, dass dieser Zugriff gut optimiert werden kann, es sei denn es ist aus dem Zusammenhang klar, dass Zugriffe auf cPoint weder p noch etwas in p verändern können. Eventuell kann man da aber mit den strict-aliasing Schaltern, die fast alle Compiler kennen, etwas machen.
-
Der Compiler wird schon checken dass "p" Alias-frei ist. Wird bloss leider nicht viel bringen, da ja abhängig von i ein anderer Wert referenziert wird, ist ja nicht immer -halfWidth für p[i][0].
Ginge höchstens wenn der Compiler sich entschliessen würde die Schleife aufzurollen, und das ist schwer einzuschätzen.
Dazu müsste ich Assembler können..
Na das solltest du wenn du auf der Ebene optimieren willst. Ist ja auch kein Ding, du musst ja bloss die wichtigsten paar Befehle kennen. So gut dass du in Assembler entwickeln könntest muss es lange nicht sein.
Wirklich Code für die "doppelte Dereferenzierung" sollte ein Compiler allerdings nicht erzeugen müssen. Der 2. Index ist jeweils Konstant, d.h. die Adresse der zu verwendenden Konstante ist
Basis + i * 16 + K. Die Konstante K kann man in die Basis mit einrechnen, und "plus Register*16" ist eine Sache die wohl die meisten CPUs können werden. D.h. der Compiler wird maximal ein oder zwei Befehle generieren, je nachdem ob die CPU "komplexe" Adressierungsarten direkt unterstützt oder noch ein LEA (load effective address) notwendig ist.
-
Warum nicht einfach per Hand unrollen?
double sin_a = std::sin(a); double cos_a = std::cos(a); double konstante_1 = halfWidth * sin_a; double konstante_2 = -konstante_1; double konstante_3 = halfWidth * cos_a; double konstante_4 = -konstante_3; double konstante_5 = halfLength * sin_a; double konstante_6 = -konstante_5; double konstante_7 = halflength * cos_a; double konstante_8 = -konstante_8; cPoints[0][0] = konstante_4 + konstante_6; cPoints[0][1] = konstante_2 + konstante_7; cPoints[1][0] = konstante_3 + konstante_6; cPoints[1][1] = konstante_1 + konstante_7; cPoints[2][0] = konstante_3 + konstante_5; cPoints[2][1] = konstante_1 + konstante_8; cPoints[3][0] = konstante_4 + konstante_5; cPoints[3][1] = konstante_2 + konstante_8;
-
asdfasd schrieb:
Warum nicht einfach per Hand unrollen?
double sin_a = std::sin(a); double cos_a = std::cos(a); double konstante_1 = halfWidth * sin_a; double konstante_2 = -konstante_1; double konstante_3 = halfWidth * cos_a; double konstante_4 = -konstante_3; double konstante_5 = halfLength * sin_a; double konstante_6 = -konstante_5; double konstante_7 = halflength * cos_a; double konstante_8 = -konstante_8; cPoints[0][0] = konstante_4 + konstante_6; cPoints[0][1] = konstante_2 + konstante_7; cPoints[1][0] = konstante_3 + konstante_6; cPoints[1][1] = konstante_1 + konstante_7; cPoints[2][0] = konstante_3 + konstante_5; cPoints[2][1] = konstante_1 + konstante_8; cPoints[3][0] = konstante_4 + konstante_5; cPoints[3][1] = konstante_2 + konstante_8;Und jetzt versuch mal den Zeitunterschied zu messen.
-
double konstante_8 = -konstante_8;Das kann doch nicht gutgehen...
-
Warum?
-
Walli schrieb:
Warum?
Weil in der Variable danach Müll steht?
-
Ja, hab eben in meiner Betriebsblindheit übersehen, dass initialisiert wird. "a = -a" ist ja in Ordnung, nur halt bei der Initialisierung nicht, weil nix vernünftiges drin stehen kann. Aber eigentlich ist ja auch "double konstante_8 = -konstante_7;" gemeint.
-
g++ produziert folgenden Code bei konstantem a:
//vom Compiler vorberechnete +-sin/cos(a)-Werte: movsd .LC1(%rip), %xmm11 movsd .LC2(%rip), %xmm0 movsd .LC3(%rip), %xmm10 movsd .LC4(%rip), %xmm9 //xmm2=halfWidth und xmm3=halfLength movsd 40(%rsp), %xmm2 movsd 32(%rsp), %xmm3 movapd %xmm2, %xmm4 movapd %xmm3, %xmm7 xorpd %xmm11, %xmm4 xorpd %xmm11, %xmm7 movapd %xmm3, %xmm12 movapd %xmm2, %xmm8 movapd %xmm4, %xmm6 mulsd %xmm10, %xmm12 mulsd %xmm0, %xmm6 movapd %xmm7, %xmm5 mulsd %xmm9, %xmm4 mulsd %xmm0, %xmm3 mulsd %xmm0, %xmm8 mulsd %xmm9, %xmm2 movapd %xmm6, %xmm13 addsd %xmm12, %xmm13 mulsd %xmm10, %xmm5 movapd %xmm4, %xmm15 mulsd %xmm0, %xmm7 addsd %xmm3, %xmm15 addsd %xmm8, %xmm12 addsd %xmm2, %xmm3 addsd %xmm5, %xmm8 addsd %xmm7, %xmm2 addsd %xmm6, %xmm5 addsd %xmm4, %xmm7Wenn a nicht zur Kompilierzeit bekannt ist, kommt ein
call sincosgegen Anfang hinzu.
Wie man sieht, bleibt hier von "doppelter Dereferenzierung" nicht viel übrig und es gibt auch keine Schleife mehr.
Die Moral von der Geschicht' ist (wie immer), dass man Mikrooptimierungen meist besser dem Compiler überlässt.