Betragsbildung, Multiplikation, Addition -> Dauer
-
Ich meinte, dass du beim Messen der Durchführungsdauer keinen Einfluss darauf hast, ob nun deine 10 additionen in 10 Takten durchgeführt werden, oder ob der Zeitschlitz gerade von einem anderen Prozess verwendet wird und deine Messung über 10 Takte benötigt. Ich habe mich definitiv nicht wiedersprochen, du wolltest nur irgendwas in meinen Satz hineininterpretieren.
Messen kannst du den Unterschied natürlich nicht, da das System die Rechenleistung auf alle laufenden Prozesse verteilt.
-
Und das ist Quatsch. Um eine sinnvolle Messung durchführen zu können, braucht man einen deterministisch definierten Fall und keinen zufälligen Programmcode. Die Messungen kannst du dir aber trotzdem sparen, weil eine moderne CPU wie schon von mir geschrieben, mehrere parallele Verarbeitungsstufen hat. Und das hat nicht die Bohne etwas mit Prozessen zu tun.
-
@HighLigerBiMBam: Es gibt da den feinen, aber wichtigen, Unterschied zwischen Echtzeit und Prozesszeit. Theoretisch kannst du solche Benchmarks auch auf einem voll ausgelasteten System durchführen und bekommst trotzdem ein brauchbares Ergebnis.
Brauchbar mit der Einschränkung, dass man nicht wirklich auf die Taktzahl schließen kann, wegen der Parallelverarbeitung, aber es ist wirklich die Zeit die dein Programm gerechnet hat.
-
Nicht nur das. Ein Betriebssystem mit seinen Unterprozessen ist in Wirklichkeit auch ein ganz anderes Programm, für die CPU, als wenn du nur eine simple Addition ausführen willst.
Nichtsdestotrotz, sind Addition und Betragsbildung bei Integern Befehle, die mit einem Takt auskommen. Weil das eine triviale Bitweise-Verknüpfung ist. Eine Multiplikation bedarf mehr Schritte. Für den Betrag gilt das selbe auch bei Float. Addition mit Float läuft bei ungleichen Exponenten auf eine zusätzliche Integer-Multiplikation hinaus. Die dadurch abgekürzt werden kann, indem die Basis zwei genutzt wird.
Optimierungen durch die Substitution von Befehlen, beispielsweise die Multiplikation mit 2, werden vom Compiler ausgeführt. Das sollte man nicht vergessen, da die Frage sich auf die Operationen in C bezog. Vorbereitende Schritte gehören in C bei den Anweisungen auch dazu. Deswegen bietet dir der Befehlssatz, auch mehrere ADD, etc. Befehle. Diese unterscheiden sich in ihrer Größe (Bitbreite) und in den Orten, wo die Werte hinterlegt sind. Für eine optimale Ausführung müssen die Werte in den Registern der CPU hinterlegt sein.
-
Paul Müller schrieb:
Nichtsdestotrotz, sind Addition und Betragsbildung bei Integern Befehle, die mit einem Takt auskommen. Weil das eine triviale Bitweise-Verknüpfung ist.
Das ist mir neu. Wie soll diese Verknüpfung denn beim Betrag aussehen? Du schreibst weiter vorne was davon, das Vorzeichenbit einfach zu entfernen. Das funktioniert aber in der Zweierkomplementardarstellung nicht. Soweit ich sehe kommt man nicht drumherum, das Vorzeichen zu testen und dann bedingt zu negieren.
-
Bashar schrieb:
Das funktioniert aber in der Zweierkomplementardarstellung nicht.
Doch gerade mit dieser funktioniert das. Schaue dir den verlinkten Wikipedia-Artikel an, wie das Zweierkomplement gebildet wird.
Beispiel: -4 (4Bit) 1100 => -8 + 4 0100 => 4
Bei Float gibt es für das Vorzeichen ein spezielles Bit.
-
Addition, Betrag, Shift ist trivial. Das ist doch alles in Hardware 'gegossen'.
Die Takte die da nötig wären, sind die zum laden und speichern der Werte.
Da musste man sich zu Zeiten von Z80 und 6502 und kurz danach noch Gedanken machen. Der 486 hatte schon den Barrel Shifter, der auch 1 .. 31 Bit in einem Takt verschiebt.
-
Paul Müller schrieb:
Bashar schrieb:
Das funktioniert aber in der Zweierkomplementardarstellung nicht.
Beispiel: -4 (4Bit) 1100 => -8 + 4 0100 => 4
Und -3 ist 1101, aber +3 ist 0011 und nicht 0101.
-
Du hast Recht. Der Inhalt wird bitweise negiert und anschließend inkrementiert. Das wären im schlimmsten Fall also zwei Takte.
-
Dazu kann man auch den Negierer und Addierer in Reihe schalten und hat gleich das richtige Ergebnis.
Das ist Hardware.
Denn die Gatter um so etwas zu machen hat man mittlerweile mehr als genug.
-
DirkB schrieb:
Dazu kann man auch den Negierer und Addierer in Reihe schalten und hat gleich das richtige Ergebnis.
Das ist Hardware.
Denn die Gatter um so etwas zu machen hat man mittlerweile mehr als genug.
Es gibt aber (bei x86) keinen Befehl zum Betrag nehmen, daher wird es wohl bei den 2 Takten bleiben. Wobei Wikipedia aber von 3 Takten spricht. Sicher, dass die vorgeschlagene Methode wasserdicht ist?
-
Man wird wohl noch prüfen, ob die Zahl wirklich negativ ist. Letztendlich müsste der Compiler aber erkennen, dass du den Betrag haben willst, um die richtige Befehlsfolge zu bilden. Es sollte aber auch nicht so schwierig den C-Code zu evaluieren. Der Test auf kleiner Null sollte identisch sein. Es ist also nur wichtig den Faktor richtig zu interpretieren. Und da hab ich bei modernen Compilern eigentlich keine Zweifel.
-
Paul Müller schrieb:
Man wird wohl noch prüfen, ob die Zahl wirklich negativ ist. Letztendlich müsste der Compiler aber erkennen, dass du den Betrag haben willst, um die richtige Befehlsfolge zu bilden. Es sollte aber auch nicht so schwierig den C-Code zu evaluieren. Der Test auf kleiner Null sollte identisch sein. Es ist also nur wichtig den Faktor richtig zu interpretieren. Und da hab ich bei modernen Compilern eigentlich keine Zweifel.
Klar erkennt der das. Ich hab' jetzt nur M16C angeguckt, da sind's nur zwei Befehle:
jpz over ;jump on plus or zero neg.w R0 ;2s complement over: ; continue with sth. else
Ganz so deterministisch kann man das trotzdem nicht sehen, weil ich nicht weiß, ob für den Compiler R0 jetzt wirklich das wichtigste ist, vllt. mag er da lieber einen Schleifenzähler unterbringen, auf jeden Fall ist vorher ein move nötig, Umladen kostet unglaublich Zeit. Im Kern sind's aber nur zwei Befehle.
Weitere Unwägbarkeiten sind momentaner Stand der Pipes und was evtl. eine Branch Prediction machen würde. Das Odd/Even- Alignment spielt ggf. auch eine große Rolle.
Die Handreichung von Renesas für's branchen lautet:2 cycles. If branched to label, the number of cycles above is increased by 2
Für das Komplement braucht die Registeradressierung nur 1 Cycle, bei indirekt- indiziert sind's 3 Cycles.
Aber was der Compiler hernimmt, ist schwer zu sagen, i.A. ist jedoch Optimierung von Hand nicht nötig.