Autor Thema: Wieviele Takte benötigt ein Befehl?  (Gelesen 24040 mal)

Argone

  • Beiträge: 10
    • Profil anzeigen
Gespeichert
« am: 26. May 2005, 12:49 »
Hat irgendjemand zufällig eine Liste, oder weiß wo es eine solche gibt, in der aufgeführt ist, wieviele Takte ein Befehl braucht?

n3Ro

  • Beiträge: 288
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 26. May 2005, 12:58 »
Da das von Prozessortyp zu Prozessortyp unterschiedlich ist kann es schwer sein eine komplette Liste mit allen Werten zu bekommen.
Agieren statt Konsumieren!

Argone

  • Beiträge: 10
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 26. May 2005, 13:00 »
Variiert das so stark bei den verschiedenen Intelprozessoren?

n3Ro

  • Beiträge: 288
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 26. May 2005, 13:04 »
Ja, weil sich z.B. das Kern Design vom Pentium zum Pentium 2/3 und auch vom Pentium 2/3 zum Pentium 4 massiv geändert hat.
Agieren statt Konsumieren!

n3Ro

  • Beiträge: 288
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 26. May 2005, 13:11 »
Kannst aber mal hier versuchen etwas brauchbares für dich zu finden:
http://cr.yp.to/hardware/x86.html
Agieren statt Konsumieren!

Argone

  • Beiträge: 10
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 26. May 2005, 13:19 »
Vielen Dank

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 26. May 2005, 16:13 »
in der ASM86FAQ stehen auch noch die zyklen für cpus von 8086 bis zum pentium 1.
Dieser Text wird unter jedem Beitrag angezeigt.

Roshl

  • Beiträge: 1 128
    • Profil anzeigen
    • http://www.lowlevel.net.tc
Gespeichert
« Antwort #7 am: 26. May 2005, 17:49 »
ausserdem ist es blödsinn einfach die taktzahlen zu addieren also meinetwegen sowas: add=5takte mov=2 takte dann sind ein mov und ein add=7, das haut nicht hin,
Grund: Out-of-Order Execution, Ausführungspipelines, die Verschiedenen Ausführungseinheiten, eventuell auftretende AGI-Stalls, und vieles mehr.
Durch entsprechende Code-Anordnung kann man erreichen das jeder befehl nur einen takt braucht (aber nur wenn keine jumps drin sind, sonst muss neu prefetched werden) man kann aber auch so dämlich anordnen, dass jeder 10 braucht oder sonstwas, selber code aber unterschiedliche taktzyklen. Also mit ner eifnachen Liste wird da nichts.
[schild=1]Wieder ein wertvoller(?) Beitrag von Roshl[/schild]

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 26. May 2005, 19:25 »
Die Liste funktioniert bei allem, was ohne Pipelines läuft, also bis zum 286er auf jeden Fall, bei 386er und 486er bin ich mir nicht sicher.
Aber ich bezweifle, dass du fuer diese Prozessoren im speziellen programmierst...

Bei den Intel-Dokus steht's fuer jeden Prozessor auch dabei, jedenfalls bei meiner 286er Doku *danke nochmal*. Ausserdem haben sich die Ausfuehrungszeiten von Befehlen mit jedem Prozessor geändert.

Svenska

Argone

  • Beiträge: 10
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 26. May 2005, 19:48 »
Dann ist das mit Codeperformance unter Assembler aber eine ziemlich schwierige Sache, oder?

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 26. May 2005, 19:55 »
Theoretisch muesstest du fuer jeden Prozessortyp (teilweise sogar
verschiedene Untertypen) gewisse Teile anders codieren.
Ich glaube nicht, dass das ein Hobbyprogrammierer hinkriegt...

Zumal es bei den neueren Prozessorn extrem viel Wissen erfordert, wenn
es um Pipelining, Registerueberschreibungen, Befehlspaarungen,
Speicherzugriffe und vieles mehr geht. Codeoptimierung ist ein extremes
Thema, stelle ich persönlich noch ne Stufe höher von der Komplexität als
OS-Programmierung. Da ist dann schon genaueste Kenntnis der
Hardware erforderlich.

Und schliesslich bewegst du dich damit auch wieder von Portabilität weg -
wobei alleine Assemblernutzung schon schlimm genug ist :)

Svenska

n3Ro

  • Beiträge: 288
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 26. May 2005, 19:59 »
Nur gut das GCC hochoptimierten Code ausspuckt und man so beruhigt in C/C++ coden kann ohne sich über die Performance sorgen zu machen ;-)
Agieren statt Konsumieren!

Argone

  • Beiträge: 10
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 26. May 2005, 20:09 »
Dann werde ich wohl doch noch C/C++ lernen müssen...

joachim_neu

  • Beiträge: 1 228
    • Profil anzeigen
    • http://www.joachim-neu.de
Gespeichert
« Antwort #13 am: 26. May 2005, 21:53 »
:D:D:D!

1. Wird NIE ein Kompiler richtig optimierten Code ausspucken, wie er schreibbar ist in ASM, weil der nie den Hintergrund dahinter erkennt und dadurch gewisse Kniffe anwenden kann.
2. Ist ASM an sich sowas von schnell und auf jeden Fall schneller als C-Code, egal, ob er optimiert ist oder nicht.
3. Mag ASM zwar nicht portabel sein, was einige sagen, dass der C-Code so viel währe. Bringt dir aber nix, weil grade auf Lowlevel-Ebene futschelste viel im Speicher rum und stellst zum Beispiel Pagingtabellen auf. Da bringt dir ein portabler Code nix, weil der eh nie auf nem anderen Prozessor laufen wird, schon alleine wegen dem Aufbau des Prozessors.

Bleibt als einziger Grund für C der Syntax und diese Strukturen, wie IF und so weiter, wodurch man wesentlich schneller coden kann.
http://www.joachim-neu.de | http://www.orbitalpirates.de | http://www.middleageworld.de

System: 256 RAM, GeForce 2 MX 400, AMD Athlon XP 1600+, Windows XP, 1x Diskette, 1x DVD-ROM, 1x CD-R(W) Brenner,...

DDR-RAM

  • Beiträge: 184
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 26. May 2005, 22:18 »
Also, wenn du dir so sicher bist, das hingefrickelter asm-code besser ist als compiler-optimierter code, würde ich dich gerne vom Gegenteil überzeugen.
Man muss nur den richtigen wählen, keinen aus der Steinzeit.
Und ich würde das glatte Gegenteil deiner 1. Aussage behaupten.
In Zukunft wird es auf jeden Fall Compiler geben, die immer den bestmöglichen Code ausspucken, wenn man nur der Compiler richtig eingestellt ist.
Deine 2. Aussage ist strange, der C-Code wird zuerst in asm-code übersetzt vom compiler. Warum soll er deshalb generell langsamer sein?
Und zu 3. kann man sich drüber streiten, klar werden einige Sachen, auf anderen Architekturen anders sein. Aber wenn du z.B. von x86 nach amd64 portierst, dann wird dir der C-Code mehr nützten, als dein asm geschreibsel, weil der Compiler für amd64 optimieren kann, der asm-code fast komplett neu geschrieben werden muss, wenn du z.B. die neuen Register nutzen willst. Auf dem alleruntersten Lowlevel-niveau kommt man zwar nicht umhin asm zu verwenden, aber ich würde möglichst viel drauf Verzichten.

Ich würde nur asm verwenden, für bottle necks (ja, die heutigen Compiler sind noch nicht das Optimum)  und lowest level.

MfG
DDR-RAM

joachim_neu

  • Beiträge: 1 228
    • Profil anzeigen
    • http://www.joachim-neu.de
Gespeichert
« Antwort #15 am: 27. May 2005, 09:38 »
1. Du willst mir allen Ernstes erklären, ein Computer wird einmal verstehen, was ein Mensch mit einer Aktion bezwecken will? Wird er nicht. Damit das ginge müsste der Mensch sich erstmal selber verstehen, was er heute in großen Bereichen noch nicht tut. Wie soll man da einen PC zu bringen, das zu verstehen? Ein PC kann zwar überlegen, was man damit meinen KÖNNTE, aber an sich verarbeitet er nur Ausdrücke und nicht, was dahinter steckt. Man könnte fast sagen, er weiß nicht, was er verarbeitet. Er verarbeitet einfach.

2. Eben aus dem Grund der "Verschrottung" durch den C-Compiler, der sicher nicht so feinen Code schreibt, den man mit ASM so oder so schreibt. Der Anwender weiß, was er verarbeitet und kann damit spielen, der PC nicht. Mach mal ne If-Konstruktion und schau, was der Compiler draus baut...

3. Es geht um "portierbar", was meines Erachtens nach eher das von Win auf Linux und Mac und umgekehrt ist. Und diese Portablilität ist bei C im Lowlevelbereich nicht gegeben, außer bei Rechnern selber Architektur. Und bei C wirste wohl auch nen Teil umschreiben dürfen, weil PM64 anderst ist als PM32. Nur im Bereich, wo man mit Standartlibs fuchtelt, da kann man portieren, ach wie toll.
http://www.joachim-neu.de | http://www.orbitalpirates.de | http://www.middleageworld.de

System: 256 RAM, GeForce 2 MX 400, AMD Athlon XP 1600+, Windows XP, 1x Diskette, 1x DVD-ROM, 1x CD-R(W) Brenner,...

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #16 am: 27. May 2005, 12:16 »
Zitat von: joachim_neu
1. Wird NIE ein Kompiler richtig optimierten Code ausspucken, wie er schreibbar ist in ASM, weil der nie den Hintergrund dahinter erkennt und dadurch gewisse Kniffe anwenden kann.


ein normalsterblicher kann vielleicht einige dutzend oder hundert zeilen assembler bis zum äußersten optimieren, aber bei einem richtigen projekt (computer spiel, betriebssystem, audio-/videocodec), wo hunderttausend zeilen code optimiert werden müssen, möchte ich das nicht von hand machen. vielleicht holt der compiler nicht aus jeder einzelnen zeile das maximum raus, aber über den ganzen code gesehen, schafft er im schnitt deutlich bessere optimierungen, als ein mensch.

spätestens wenn es darum geht multithreading programme zu optimieren, wird es viel zu kompliziert für einen menschen. da werden im c-code ein paar "hints" (bei OpenMP z.b. irgendein #pragma) gesetzt und dann legt der c-compiler eine for-schleife so außeinander, dass der code in zum beispiel 8 threads aufgeteilt wird. da muss sich der mensch keine gedanken machen, wie man die synchronisiert und ob es so praktisch überhaupt funktionieren kann, und so weiter, weil der compiler es einfach tut. (oder eine fehlermeldung ausgibt, wenn es doch nicht gehen sollte.)
Dieser Text wird unter jedem Beitrag angezeigt.

Roshl

  • Beiträge: 1 128
    • Profil anzeigen
    • http://www.lowlevel.net.tc
Gespeichert
« Antwort #17 am: 27. May 2005, 12:24 »
Also ich weiss nicht ob die Leute die sagen Compiler code sei dem ASM code vom Menschen ebenbürtig sich einmal vom Compiler den Code als Assemblat haben geben lassen. Ich krieg manchmal total das kotzten was gcc abliefert und das bei Optimierung -O3.
Bei OS-Programmierung kommt man aber eh nicht drum rum manchmal mit ASM arbeiten zu müssen, also ist man immer irgendwo Plattform gebunden und muss für jede Plattform anderen Code schreiben, auch dem Compiler muss man sagen, auf welche Plattform er ausgerichtet sein soll.
Für AMD64 muss man auch seinen C-Code neu schreiben, da ja vieles wegfällt, z.b. muss man zwangsläufig Softwaretaskswitching verwenden. Wenn man bisher TSS benutzt hat, muss man auch den C-Code ändern.

PS: Alle Aussagen gelten nur, wenn der, der Asm codet das auch wirklich(!) beherrscht. Komplett in Asm geschriebenes OS muss nicht schneller sein, wenn der Code schrott ist. Aber man kann genauso in C totalen scheiss zusammencoden und der Compiler kann da auch nix optimieren.
[schild=1]Wieder ein wertvoller(?) Beitrag von Roshl[/schild]

DDR-RAM

  • Beiträge: 184
    • Profil anzeigen
Gespeichert
« Antwort #18 am: 27. May 2005, 13:02 »
Also als erstes zählen, die Algorithmen.
Basic QuickSort ist schneller als asm bubble sort, wenn man 20k Elemente sortieren will.
Bei asm kann man viel falsch machen, bei C dagegen fast nichts.

Hm, also ich bringe nochmal ein Beispiel für C-Code und den asm-code dazu:


bool IsPrime(unsigned int x)
{
switch (x)
{
case 0:
case 1:
return false;
case 2:
return true;
default:
if (x % 2 == 0)
return false;
for (unsigned int i = 3;  i < fastIntSqrt(x); i++)
{
if (x % i == 0)
return false;
}
return true;
}
}


(ja, ist C++, wegen bool)
und jetzt der asm-code (mit dem C-Code dazwischen)


bool IsPrime(unsigned int x)
{
  push        ebx  
  mov         ebx,eax
switch (x)
  cmp         ebx,1
  jbe         IsPrime+11h (4010B1h)
  cmp         ebx,2
  jne         IsPrime+15h (4010B5h)
case 2:
return true;
  mov         al,1
  pop         ebx  
}
}
  ret              
{
case 0:
case 1:
return false;
  xor         al,al
  pop         ebx  
}
}
  ret              
default:
if (x % 2 == 0)
  test        bl,1
return false;
  je          IsPrime+11h (4010B1h)
  push        esi  
for (unsigned int i = 3;  i < fastIntSqrt(x); i++)
  mov         esi,3
  call        fastIntSqrt (401000h)
  mov         ecx,eax
  cmp         ecx,esi
  jbe         IsPrime+41h (4010E1h)
  jmp         IsPrime+30h (4010D0h)
  lea         ecx,[ecx]
{
if (x % i == 0)
  xor         edx,edx
  mov         eax,ebx
  div         eax,esi
  test        edx,edx
  je          IsPrime+46h (4010E6h)
  add         esi,1
  cmp         esi,ecx
  jb          IsPrime+30h (4010D0h)
  pop         esi  
}
return true;
  mov         al,1
  pop         ebx  
}
}
  ret              
  pop         esi  
return false;
  xor         al,al
  pop         ebx  
}
}
  ret      


Was kann man da noch großartig optimieren?
Achso, der Compiler hat nicht c-aufrufkonvention genommen, sondern einfach x per eax übergeben! Ist übrigens MS VC++, weiß nich, ob gcc das auch machen kann.

Die stellen, wo der Compiler scheiße ausspuckt sind imo sehr selten und ich guck mir eigentlich immer den asm-code an, damit ich sehe, das er net nur scheiße macht.
Also, ohne Optimierung ist klar, das des net gut ist, aber mit -O3?
gebe mal Beispiel :D
Ok, teilweise sind einige stellen redundant, aber sowas zu erkennen, noch ein, zwei Jahre und Handoptimierungen kann man sich gänzlich sparen (vor allem auch weil für verschiedene CPU's unterschiedlich optimiert werden muss, beim Compiler einfach switch für ne andere Cpu angeben, aber asm muss neucoden)
Ich bin zuversichtlich!

MfG
DDR-RAM

joachim_neu

  • Beiträge: 1 228
    • Profil anzeigen
    • http://www.joachim-neu.de
Gespeichert
« Antwort #19 am: 27. May 2005, 13:16 »
1. In ASM nehme man eine Call-Table bei den Switches, spart alle CMPs und alle JMPs.
2. Da sind noch nicht die Strukturen mit drinnen.

Lass es mal komplett auskompilieren. ;)
http://www.joachim-neu.de | http://www.orbitalpirates.de | http://www.middleageworld.de

System: 256 RAM, GeForce 2 MX 400, AMD Athlon XP 1600+, Windows XP, 1x Diskette, 1x DVD-ROM, 1x CD-R(W) Brenner,...

 

Einloggen