wpc115
-
DennisB schrieb:
Dann wirst du feststellen, dass die Aufgabe ein Witz sein muss.

warum?
-
volkard schrieb:
DennisB schrieb:
Dann wirst du feststellen, dass die Aufgabe ein Witz sein muss.

warum?
5 Multiplikationen, 6 Additionen und 6 mal subtrahieren.
Das ganze 10 Minuten nachdem der unoptimiere Prototyp fertig war, alles in allen vielleicht 20 Minuten "Arbeitsaufwand".
Wenns schneller geht, ich wüsste gerne wie!
-
Jo, da haben wir wohl identischen Code fabriziert *g*
Habe mich auch gewundert...
Geht das noch schneller?
-
ich baue noch am testefälle-erzeuge-und-mess-programm.
warum sollte es nicht schneller gehen? ich glaub' da ist noch was drin.
wenn ich erste ergebnisse habe, poste ich sie in nem thread namens wpc116.
-
also ich habe 6- 5+ und 5*
also ein + weniger
aber den unterschied macht auf jeden fall der zugriff auf die einzellnen zahlen
da hebe ich die unterschiede meiner versuche drastisch gemerktcu
-
Headhunter schrieb:
volkard schrieb:
DennisB schrieb:
Dann wirst du feststellen, dass die Aufgabe ein Witz sein muss.

warum?
5 Multiplikationen, 6 Additionen und 6 mal subtrahieren.
jo, genau das hab ich auch..
hm korrektur.. doch 5* 5+ und 6-
-
stahl schrieb:
Headhunter schrieb:
volkard schrieb:
DennisB schrieb:
Dann wirst du feststellen, dass die Aufgabe ein Witz sein muss.

warum?
5 Multiplikationen, 6 Additionen und 6 mal subtrahieren.
jo, genau das hab ich auch..
hm korrektur.. doch 5* 5+ und 6-
Mmh, auch verzählt.
Hab auch die gleichen Werte
-
Ich auch

-
was denkt ihr über meine lösung:
int wpc116b(char* t1, char* t2) { double t1stund, t1minut, t1sekund=0.0;//var von t1 double t2stund, t2minut, t2sekund; // t2 var's sscanf(t1, "%f:%f:%f", &t1stund , &t1minut, & t1sekund);//umwnadeln v.t1 nach zeit sscanf(t2, "%f:%f:%f", &t2stund, &t2minut, &t2sekund); //t2 umwadneln double zeit1 = t1sekund+t1minut *60+t1stund* 60.0* 60; double zeit2= t2sekund+t2minut *60+t2stund *60 *60.0;//doppelt mahl nehmen return int(zeit2- zeit1);//dieferenz ist zeitsekunden zw. t1&t2 }
-
also deine version ist auf meinem rechner ca. 425 mal langsamer als meine, es gilt also weiter zu optimieren ...
ein kleiner vorschlag, der schon was bringen sollte:
du kannst 60*60 bzw. auch *60 ausklammern (die beiden zeiten als differenz betrachtet)
du hast ja:
t1=s1 + m1*60 + h1*3600
t2=s2 + m2*60 + h2*3600und dann:
t2-t1
das heißt:
(s2 + m2*60 + h2*3600) - (s1 + m1*60 + h1*3600)wird zu:
(s2-s1) + (m2-m1)*60 + (h2-h1)*3600
außerdem wären variablen vermeidbar, was das erzeugen dieser überflüssig macht und somit auch schneller sein sollte
-
Sword_Master schrieb:
was denkt ihr über meine lösung:
int wpc116b(char* t1, char* t2) { double t1stund, t1minut, t1sekund=0.0;//var von t1 double t2stund, t2minut, t2sekund; // t2 var's sscanf(t1, "%f:%f:%f", &t1stund , &t1minut, & t1sekund);//umwnadeln v.t1 nach zeit sscanf(t2, "%f:%f:%f", &t2stund, &t2minut, &t2sekund); //t2 umwadneln double zeit1 = t1sekund+t1minut *60+t1stund* 60.0* 60; double zeit2= t2sekund+t2minut *60+t2stund *60 *60.0;//doppelt mahl nehmen return int(zeit2- zeit1);//dieferenz ist zeitsekunden zw. t1&t2 }jaja TomasRiker
-
ok, doch keine optimierung.
ich dachte, an den teuren multiplikationen können man hin und wieder eine sparen. aber selbst in der ersten ziffer ein if(d) result+=d*36000 ist langsamer, als stur zu multiplizieren.
-
Ausmultiplizieren scheint auch Wurst zu sein. Egal ob mit oder ohne Klammern und egal wie oft ich multipliziere, der Compiler optimiert das immer weg.
-
Der Compiler macht aus den Multiplikationen wahrscheinlich sowieso irgendwelche Bit-Shifts, oder?
-
@TomasRiker: keine ahnung, jedenfalls ist meine version mit bit-shifts statt multiplikationen langsamer als mit normalen
zur erklärung:
a*3600 = a<<12-a<<9+a<<4
doch dass ist langsamer und besseres ist mir bei bit-shift nicht eingefallen
-
Ich habe mir von VC++ mal den Assembler-Code von der optimierten Version ausgeben lassen. Dort ist kein "mul" oder "imul" zu finden. Es ist mir ehrlich gesagt rätselhaft, wie dieser Code überhaupt funktionieren kann (tut er aber!).
00000 8b 4c 24 04 mov ecx, DWORD PTR _t1$[esp-4] 00004 8b 54 24 08 mov edx, DWORD PTR _t2$[esp-4] 00008 0f be 02 movsx eax, BYTE PTR [edx] 0000b 56 push esi 0000c 0f be 31 movsx esi, BYTE PTR [ecx] 0000f 2b c6 sub eax, esi 00011 0f be 71 01 movsx esi, BYTE PTR [ecx+1] 00015 8d 04 80 lea eax, DWORD PTR [eax+eax*4] 00018 d1 e0 shl eax, 1 0001a 2b c6 sub eax, esi 0001c 0f be 72 01 movsx esi, BYTE PTR [edx+1] 00020 03 c6 add eax, esi 00022 0f be 71 03 movsx esi, BYTE PTR [ecx+3] 00026 8d 04 40 lea eax, DWORD PTR [eax+eax*2] 00029 d1 e0 shl eax, 1 0002b 2b c6 sub eax, esi 0002d 0f be 72 03 movsx esi, BYTE PTR [edx+3] 00031 03 c6 add eax, esi 00033 0f be 71 04 movsx esi, BYTE PTR [ecx+4] 00037 8d 04 80 lea eax, DWORD PTR [eax+eax*4] 0003a d1 e0 shl eax, 1 0003c 2b c6 sub eax, esi 0003e 0f be 72 04 movsx esi, BYTE PTR [edx+4] 00042 03 c6 add eax, esi 00044 0f be 71 06 movsx esi, BYTE PTR [ecx+6] 00048 0f be 49 07 movsx ecx, BYTE PTR [ecx+7] 0004c 8d 04 40 lea eax, DWORD PTR [eax+eax*2] 0004f d1 e0 shl eax, 1 00051 2b c6 sub eax, esi 00053 0f be 72 06 movsx esi, BYTE PTR [edx+6] 00057 0f be 52 07 movsx edx, BYTE PTR [edx+7] 0005b 03 c6 add eax, esi 0005d 8d 04 80 lea eax, DWORD PTR [eax+eax*4] 00060 d1 e0 shl eax, 1 00062 2b c1 sub eax, ecx 00064 03 c2 add eax, edx 00066 5e pop esi
-
EDIT: mal genau überprüft, so sieht auch mein asm aus
cu
-
Aber wie funktioniert dieser Code?
Wo stehen die Multiplikation mit 36000, 3600, 600, 60 und 10?EDIT:
Witzig ist Folgendes: wenn ich mit 36001 multipliziere, steht auf einmal folgendes im Code:imul edi, 36001Irgendwie produziert der Compiler aus der 10 die 60, aus der 60 die 600 usw.. Echt nicht übel, hätte ich nicht gedacht, dass der so gut optimiert!
-
kenn mich mit asm nicht so besonders aus, aber habe gerade per hilfe rausgefunden, dass multiplikationen wohl
"als Folge von Schiebe- und LEA-Anweisungen zu implementieren" sind
hatte in der hilfe einfach mal nach "lea" gesucht
hier ein bsp. aus der hilfe!!:
<ZITAT>
Das nachfolgende Codebeispiel zeigt den Unterschied zwischen den Optionen Weniger Code bevorzugen (/Os) und Schnellen Code bevorzugen (/Ot):
/* differ.c
Dieses Programm implementiert einen Multiplikations-
Operator.
Mit /Os kompilieren, um Multiplizieren explizit als Multiplizieren zu implementieren.
Mit /Ot kompilieren, um als Folge von Schiebe- und LEA-Anweisungen zu implementieren.
*/
int differ(int x)
{
return x * 71;
}Der nachfolgende Ausschnitt aus dem Maschinen-Code zeigt, daß der Compiler den Multiplikationsausdruck in der Return-Anweisung explizit als eine Multiplikation implementiert, um eine kurze, aber langsamere Codefolge zu erzeugen, wenn bei der Kompilierung von DIFFER.C weniger Code bevorzugt wird (/Os):
mov eax, DWORD PTR _x$[ebp]
imul eax, 71 ; 00000047HWenn bei der Kompilierung von DIFFER.C dagegen Geschwindigkeit bevorzugt wird (/Ot), implementiert der Compiler den Multiplikationsausdruck in der Return-Anweisung als eine Folge von Schiebe- und LEA-Anweisungen, um eine schnelle, aber längere Codefolge zu erzeugen:
mov eax, DWORD PTR _x$[ebp]
mov ecx, eax
shl eax, 3
lea eax, DWORD PTR [eax+eax*8]
sub eax, ecx</ZITAT>
-
Interessant ist, wie er erst eax = t2[0]-t1[0] berechnet, was ja durchaus nicht verkehrt ist, dann aber eax als Zeiger verwendet (lea eax, DWORD PTR [eax+eax*4]). Kann aber auch sein, dass ich mich verguckt habe, AT&T Syntax ist doch ein wenig anders.