Was ist rechnerisch schneller? simple formel
-
b7f7 schrieb:
Ausserdem ist geschwindigkeit keine frage der wirkenden beschleunigung sondern eine frage der Reibung, Fallhöhe usw. was das Fallen auf der Venus etwas problematisch macht denk ich.
hmm, also ich habe nächste woche meine physik matur und dachte ich hätte alles im griff. aber nach diesem schocker (geschwindigkeit ist keine frage der beschleunigung, aber der reibung) muss ich wohl alles nochmal repetieren...
nur so als anmerkung... reibung ist eine kraft welche dividiert durch die masse des objektes die wirkende beschlenigung ergibt. ich schlussfolgere also, dass reibung auch nichts mit der geschwindigkeit zu tun hat.
ausserdem bin ich mir darüber nicht im klare, warum das fallenlassen auf der venus ein problem sein soll? ok, der apfel würde wohl auf der venus nicht lange durchhalten, aber die asche des apfels würde runterfallen, da bin ich mir sicher. (wobei vielleicht gibts da auch wind.....)
-
ich hab auch mal einen "sinnvollen" test gemacht:
int function1(int i) { return i<<1; } int function2(int i) { return i*2; } int main() { cout << function1(rand()); cout << function2(rand()); }
wie ich erwartet hatte macht der compiler beide funktionen zum selben code... erstaunlich ist aber, dass weder ein shift noch eine multiplikation vorkommt. er addiert i einfach zu sich selbst:
.align 2 .globl __Z9function1i .def __Z9function1i; .scl 2; .type 32; .endef __Z9function1i: LFB1: pushl %ebp LCFI0: movl %esp, %ebp LCFI1: movl 8(%ebp), %eax addl %eax, %eax popl %ebp ret LFE1: .align 2 .globl __Z9function2i .def __Z9function2i; .scl 2; .type 32; .endef __Z9function2i: LFB2: pushl %ebp LCFI2: movl %esp, %ebp LCFI3: movl 8(%ebp), %eax addl %eax, %eax popl %ebp ret LFE2:
schlussfolgerung: der compiler weiss es eh besser und diese mikrooptimierungen, die schon seit etwa 20 jahren in programmiererkreisen kursieren, sind (man glaubt es kaum) auch schon zu den compilerprogrammierern vorgedrungen und die haben die in ihre compiler eingebaut
.
da sag ich nur: DIESE SCHWEINE wir geben uns hier 8 threadseiten lang mühe und den compiler interessiert das nicht die bohne!ändert man den code übrigens zu
int function1(int i) { return i<<2; } int function2(int i) { return i*4; }
ab, dann wird die multiplikation durch einen shift ersetzt... daher sollte man hier wohl nicht das nehmen was "optimierter" aussieht, sondern das, was der code darstellen soll. wenn es um arithmetik get multipliziert man und wenn es um bitoperationen geht dann shiftet man.
-
Es geht ja nicht darum, ob man Shifts schreibt oder Multiplikationen. Es geht darum, dass wenn man irgendwas mit 250 hat, dass man vielleicht stattdessen 256 nimmt.
Mehrdimensionales Array 3x3:
AAAXBBBXCCCX
Hier hab ich einfach mal frech eine 4x4 Array draus gemacht und Dummys eingesetzt. Jetzt komm ich von auf [x,0] mit x*4 ( == << 2) anstatt *3 zu rechnen.
Dass der Compiler aus *4 nen << 2 macht, hat ja nie einer (wirklich nicht?!?
) bestritten.
und diese mikrooptimierungen, die schon seit etwa 20 jahren in programmiererkreisen kursieren, sind (man glaubt es kaum) auch schon zu den compilerprogrammierern vorgedrungen und die haben die in ihre compiler eingebaut
.
Zumindest das hast du schön gesagt.
-
Leute können wir nun zu einem Fazit kommen was nun schneller ist?
-
b7f7 schrieb:
MaSTaH schrieb:
Also wenn ich durch ein paar Änderungen "nur" 10% Performance gewinne dann mache ich sie! Intel ist auch doof, oder? Entwickeln die nen Dothan um ein paar Prozent rauszuholen...
Die frage ist eigentlich wo ich die 10% schaffe
Ich denke die 80:20-Regel wurde oft genug erwähnt.
Wobei es doch nicht so ist, dass der Compiler zu dumm ist um ne Multiplikation mit einer konstanten 2er-Potenz zu erkennen. Wichtig ist, dass man bei den wichtigen 20 Prozent nicht so oft in die Verlegenheit kommt eine Multiplikation (oder noch teurer Division) mit nicht-Zweierpotenzen zu verwenden, indem man z.B. bei Texturen oder Auflösungen die Dimensionen in Zweierpotenzen, oder zumindest Kombinationen davon (32+64+128+256=480; 128+512=640; 512+256=768; 1024; 128+1024=1152; 256+1024=1280 ... Zufall?) wählt, damit dann die Divisionen und Multiplikationen möglichst durch Rechts- und Linksshifts ersetzt werden können. Das kann man dann wenn man will selber machen, oder es dem Compiler überlassen (oben hat man ja schön gesehen, dass er z.B. aus i*2 nicht i<<1 sondern i+i macht).
-
japro schrieb:
hmm, also ich habe nächste woche meine physik matur und dachte ich hätte alles im griff. aber nach diesem schocker (geschwindigkeit ist keine frage der beschleunigung, aber der reibung) muss ich wohl alles nochmal repetieren...
ist keine Frage der Beschleunigung alein.
nach deiner aussage würde man auch 2 kugeln fallen lassen können
beide auf der erde. aber ohne randbedingungen.
dh. ich lasse eine von 10m höhe fallen und die andere von 1m höhe. und stelle danach fest das die endgeschwindigkeit der ersten höher ist.
irgendwan kommt man mit denken aber trotzdem dahin das geschwindigkeit von einer kraft und der Zeit der einwirkung abhängt.
was ich meinte ist das man durch richtige defiition sogar vernünftige werte aus deinem Venus Mond Beispiel ziehn kann.
man betrachtet halt alles in einem anderen system. aber regal.
-
[quote="MaSTaH"][quote="b7f7"]
MaSTaH schrieb:
Wichtig ist, dass man bei den wichtigen 20 Prozent nicht so oft in die Verlegenheit kommt eine Multiplikation (oder noch teurer Division) mit nicht-Zweierpotenzen zu verwenden, indem man z.B. bei Texturen oder Auflösungen die Dimensionen in Zweierpotenzen, oder zumindest Kombinationen davon (32+64+128+256=480; 128+512=640; 512+256=768; 1024; 128+1024=1152; 256+1024=1280 ... Zufall?) wählt, damit dann die Divisionen und Multiplikationen möglichst durch Rechts- und Linksshifts ersetzt werden können. Das kann man dann wenn man will selber machen, oder es dem Compiler überlassen (oben hat man ja schön gesehen, dass er z.B. aus i*2 nicht i<<1 sondern i+i macht).
Ich denke der Hauptvorteil ist, dass man die natürlichen Busbreiten benutzt und keine memorylücken durch die Datenanordnung hat
-
japro schrieb:
int function1(int i) { return i<<2; } int function2(int i) { return i*4; }
DEr VC 6 copiler finded es hier besser beide sachen durch
lea Reg,[mem*4]
zu ersetzen
intel sagt
INTEL schrieb:
Use of the shift and rotate Instructions
The shift and rotate instructions have a longer latency on the
Pentium 4 processor than on previous processor generations. The
latency of a sequence of adds will be shorter for left shifts of three or
less. Fixed and variable shifts have the same latency.
The rotate by immediate and rotate by register instructions are more
expensive than a shift. The rotate by 1 instruction has the same
latency as a shift.
-
ist keine Frage der Beschleunigung alein.
nach deiner aussage würde man auch 2 kugeln fallen lassen können
beide auf der erde. aber ohne randbedingungen.
dh. ich lasse eine von 10m höhe fallen und die andere von 1m höhe. und stelle danach fest das die endgeschwindigkeit der ersten höher ist.
irgendwan kommt man mit denken aber trotzdem dahin das geschwindigkeit von einer kraft und der Zeit der einwirkung abhängt.
was ich meinte ist das man durch richtige defiition sogar vernünftige werte aus deinem Venus Mond Beispiel ziehn kann.
man betrachtet halt alles in einem anderen system. aber regal.meine analogie war wohl zu komplex... das apfel und birne auf der erde gleich schnell fallen weiss ich auch. also nochmal für alle zum mitschreiben:
du wolltest mit deinem beispiel zeigen, dass ein shift schneller als eine multiplikation ist, was laut meiner meinung nicht der fall ist. d.h. apfel(shift) und birne (multiplikation) sind gleich schnell. du benutzt aber um das gegenteil zu beweisen für den shift den ausdruck x<<1 (mond) und für die multiplikation den ausdruck x*x (venus). die sind nämlich garnicht sinnvoll vergleichbar.
mit der selben argumentation wie deiner (für einen bestimmten wert x ist das aber gleich) könnte ich ja folgendes beispiel konstruieren:
int i=1; for(unsigned int j=0;j<100000000;++j) i=(i*2)/2; for(unsigned int k=0;k<100000000;++k) i=(i<<i)/2;
resultat:
x*2: 1035543157 x<<x: 1299119006
auf diese art kann man beispiele erzeuge die beweisen, was einem gerade gefällt.
p.s. ich weiss ja nicht was du alles an randbedingungen verlangs bei experiementbeschreibungen. wenn ich fallgeschwindigkeiten von verschiedenen objekten vergleiche, impliziere doch einfach, dass sie von derselben höhe fallengelassen werden, wenn nicht anders angegeben. normalerweise gibt man an was man vergleicht. d.h. was die variable ist und die ist hier die art des objektes. den rest impliziert man als identisch, falls nicht explizit anders spezifiziert... sonst müsste ja jede experimentbeschreibung ein 100seiten starkes dokument sein welches ort, luftfeuchtigkeit, medium, messinstrument, luftdruck, temperatur ..... explizit festlegt.
-
dann vergleichen wir halt so da deken sich auch die Resultate mit INTEL
{ for(unsigned int j=0;j<1000000000;++j) _asm{ push eax mov eax,3 shl eax,3 pop eax } } { for(unsigned int k=0;k<1000000000;++k) _asm{ push eax mov eax,3 imul eax,8 pop eax } } { for(unsigned int k=0;k<1000000000;++k) _asm{ push eax mov eax,3 add eax,3 add eax,3 add eax,3 add eax,3 add eax,3 add eax,3 add eax,3 pop eax } } { for(unsigned int k=0;k<1000000000;++k) _asm{ push eax mov eax,3 add eax,eax add eax,eax add eax,eax pop eax } }
Out Shift: 4.78634 Imul: 3.19394 ADD: 3.1026 ADD2: 2.10263
das beweist nur das nen shiftleft eigentlich gleich schnell ist wie imul sogar eigentlich langsamer (AufP4)
die 0,5s die ich gepostet hatte fallen bei der hohen anzahl an durchläufen garnicht auf aber die wertung hatte ich da ja offen gelassen.
EDIT:btw mov eax,3*8 hab ich einfach mal weggelassen