Warum dauert die Hardware-Division so viel länger als die Multiplikation auf einem Mikrocontroller? Beispielsweise dauert eine Division auf einem dsPIC 19 Zyklen, während eine Multiplikation nur einen Taktzyklus benötigt.
Ich habe einige Tutorials durchgearbeitet, darunter den Divisionsalgorithmus und den Multiplikationsalgorithmus auf Wikipedia. Hier ist meine Begründung.
Ein Divisionsalgorithmus ist wie eine langsame Divisionsmethode mit Wiederherstellung auf Wikipedia ein rekursiver Algorithmus. Dies bedeutet, dass (Zwischen-)Ergebnisse aus Schritt k
als Eingaben für Schritt verwendet werden k+1
, was bedeutet, dass diese Algorithmen nicht parallelisiert werden können. Daher dauert es mindestens n
Zyklen, um die Division abzuschließen, während n
ein Dividend eine Anzahl von Bits ist. Für 16-Bit-Dividenden entspricht dies mindestens 16 Zyklen.
Ein Multiplikationsalgorithmus muss nicht rekursiv sein, was bedeutet, dass es möglich ist, ihn zu parallelisieren. Es gibt jedoch viele verschiedene Multiplikationsalgorithmen, und ich habe keine Ahnung, welcher von Mikrocontrollern verwendet werden kann. Wie funktioniert die Multiplikation auf einer Hardware/einem Mikrocontroller?
Ich habe einen Dadda-Multiplikator -Algorithmus gefunden, der nur einen Taktzyklus dauern soll, um fertig zu werden. Was ich hier jedoch nicht verstehe ist, dass Daddas Algorithmus in drei Schritten vorgeht, während Ergebnisse aus Schritt 1 in Schritt 2 verwendet werden usw. Demnach würde dies mindestens drei Taktzyklen dauern, bis dies abgeschlossen ist.
Ein Teiler bildet viel weniger elegant auf typische Hardware ab. Nehmen Sie Lattice ICE40 FPGAs als Beispiel.
Vergleichen wir zwei Fälle: diesen 8x8-Bit-zu-16-Bit-Multiplikator:
module multiply (clk, a, b, result);
input clk;
input [7:0]a;
input [7:0]b;
output [15:0]result;
always @(posedge clk)
result = a * b;
endmodule // multiply
und dieser Teiler, der 8- und 8-Bit-Operanden auf 8-Bit-Ergebnis reduziert:
module divide(clk, a, b, result);
input clk;
input [7:0] a;
input [7:0] b;
output [7:0] result;
always @(posedge clk)
result = a / b;
endmodule // divide
(Ja, ich weiß, die Uhr macht nichts )
Eine Übersicht über den generierten Schaltplan bei der Abbildung des Multiplikators auf ein ICE40-FPGA finden Sie hier und den Teiler hier .
Die Synthesestatistiken von Yosys sind:
Es ist erwähnenswert, dass die Größe des generierten Verilogs für einen Multiplikator voller Breite und einen Teiler mit maximaler Teilung nicht so extrem ist. Wenn Sie sich jedoch die Bilder unten ansehen, werden Sie feststellen, dass der Multiplikator vielleicht eine Tiefe von 15 hat, während der Teiler eher wie 50 oder so aussieht; der kritische Weg (dh der längste Weg, der im Betrieb auftreten kann) bestimmt die Geschwindigkeit!
Sie werden dies sowieso nicht lesen können, um sich einen visuellen Eindruck zu verschaffen. Ich denke, die Unterschiede in der Komplexität sind möglich zu erkennen. Dies sind Einzelzyklus-Multiplikatoren/Teiler!
Multiplizieren auf einem ICE40 (Warnung: ~100 Mpixel Bild)
( Teilen auf einem ICE40 ) (Warnung: ~100 Mpixel Bild)
yosys
, read_verilog multiply.v
, synth_ice40
, show -format svg -prefix multiply_ice40
. Aber warten Sie, ich werde das mit wiederholen, show -viewer /bin/true -prefix multiply_ice40
um die .dot-Dateien zu erhalten :)Wir können mehrere Logikschichten pro Taktzyklus haben, aber es gibt eine Grenze, wie viele Logikschichten wir genau haben können und wie komplex diese Schichten sein können, hängt von unserer Taktgeschwindigkeit und unserem Halbleiterprozess ab.
Es gibt jedoch viele verschiedene Multiplikationsalgorithmen, und ich habe keine Ahnung, welcher von Mikrocontrollern verwendet werden kann
Die meisten Multiplikationen in Computern verwenden eine Variante der binären langen Multiplikation. Binäre lange Multiplikation beinhaltet
Werfen wir also einen Blick auf die Implementierung in Hardware.
Lassen Sie uns also festhalten, wie viele Logikstufen wir für einen 8x8-Multiplikator mit 16-Bit-Ergebnissen benötigen. Nehmen wir der Einfachheit halber an, wir versuchen nicht, die Tatsache zu optimieren, dass nicht alle Zwischenergebnisse Bits an allen Positionen haben.
Nehmen wir an, dass ein Volladdierer in zwei "Gatterstufen" implementiert ist.
Insgesamt also etwa 41 Logikstufen. Die meisten davon werden für die Addition der letzten beiden Zwischenergebnisse aufgewendet.
Dies könnte weiter verbessert werden, indem die Tatsache ausgenutzt wird, dass nicht bei allen Zwischenergebnissen alle Bits vorhanden sind (das ist im Grunde das, was der Dada-Multiplikator tut), indem für den letzten Schritt ein Carry-Lookahead-Addierer verwendet wird. Durch Hinzufügen von 7 Zahlen, um 3 statt drei zu erzeugen, um zwei zu erzeugen (Reduzierung der Anzahl der Stufen zum Preis von mehr Toren und breiteren Toren) usw.
Das sind jedoch alles Kleinigkeiten, der wichtige Punkt ist, dass die Anzahl der Stufen, die benötigt werden, um zwei n-Bit-Zahlen zu multiplizieren und ein 2n-Bit-Ergebnis zu erzeugen, ungefähr proportional zu n ist.
Wenn wir uns andererseits Divisionsalgorithmen ansehen, stellen wir fest, dass sie alle einen iterativen Prozess haben, bei dem.
Die Anzahl der zur Implementierung der Division erforderlichen Logikstufen ist also ungefähr proportional zu n zum Quadrat.
Die langsame Teilung ist von Natur aus iterativ, sodass sie tendenziell länger dauert. Es gibt etwas schnellere langsame Divisionsalgorithmen als die einfachen, die Nachschlagetabellen verwenden. Der SRT-Algorithmus erzeugt zwei Bits pro Zyklus. Ein Fehler in einer solchen Tabelle war die Ursache für den berüchtigten Pentium-FDIV-Bug (ca. 1994). Dann gibt es sogenannte schnelle Divisionsalgorithmen.
Natürlich könnte man im Prinzip einfach eine riesige Nachschlagetabelle verwenden, um das Produkt oder den Quotienten zweier Zahlen zu berechnen und so Ergebnisse in einem einzigen Zyklus zu erhalten, aber das wird mit zunehmender Anzahl von Bits pro Zahl schnell unpraktisch.
Praktische Divisionsalgorithmen basieren alle auf Zahlenfolgen, die gegen den Quotienten konvergieren.
Es gibt additive Methoden, wie Non-Restoring oder SRT, die funktionieren, indem 2^N zum Quotienten addiert oder entfernt wird und entsprechend der 2^N * Divisor zum Teilrest addiert oder entfernt wird, bis er gegen Null konvergiert ist.
Es gibt multiplikative Methoden wie Newton-Raphson oder Goldshmidth, bei denen es sich um Methoden zur Wurzelfindung handelt, bei denen die Division als Umkehrung der Multiplikation berechnet wird.
Additive Verfahren ergeben ein oder wenige Bits pro Zyklus. Multiplikative Verfahren verdoppeln die Anzahl der Bits für jeden Zyklus, erfordern jedoch eine anfängliche Annäherung, die häufig mit einer konstanten Tabelle erhalten wird.
Die Bezeichnungen "langsam" und "schnell" sind irreführend, da die tatsächliche Geschwindigkeit von der Anzahl der Bits abhängt, wie viel Hardware für die Funktion verwendet wird (und ein schneller Multiplikator sehr groß ist) ...
Die Division ist langsamer als die Multiplikation, da es keine direkte, parallele Methode zu ihrer Berechnung gibt: Entweder gibt es eine Iteration, oder es wird Hardware kopiert, um die Iteration als kaskadierte (oder Pipeline-) Blöcke zu implementieren.
Ein Divisionsalgorithmus (tatsächlich jeder Algorithmus) kann in einem Taktzyklus durchgeführt werden. Wenn Sie bereit sind, für die zusätzlichen Transistoren und die niedrigere zulässige Taktrate zu zahlen.
Angenommen, Sie haben eine Reihe von Gattern, die einen Taktzyklus eines vorhandenen Mehrzyklus-Divisionsalgorithmus implementieren. Um den Algorithmus zu einem Einzelzyklus zu machen, verwenden Sie mehrere Hardwarestufen (ähnlich derjenigen, die in einer Stufe des Mehrzyklusalgorithmus verwendet wird), wobei die Ausgabe einer Stufe die nächste Stufe speist.
Der Grund, es nicht so zu machen, ist natürlich, dass es viele Transistoren verwendet. Beispielsweise kann es für eine 16-Bit-Division fast 16 x mehr Transistoren verwenden. Außerdem senkt das Vorhandensein von mehr Gatterstufen die maximal zulässige Taktfrequenz (weil es mehr Stufen der Ausbreitungsverzögerung gibt).
Warum dauert die Hardware-Division so viel länger als die Multiplikation auf einem Mikrocontroller?
Das ist keine Elektronikfrage. Bestenfalls ist es eine Computerfrage, besser an Stack Overflow gerichtet.
Siehe zum Beispiel hier: Ist die Multiplikation schneller als die Float-Division?
In Wirklichkeit ist es eine Frage aus dem wirklichen Leben: Warum dauert die Division so viel länger als die Multiplikation?
Was würden Sie lieber auf Papier berechnen?
51 * 82
oder
4182 / 51
Division dauert länger als Multiplikation , weil es schwieriger ist .
Eugen Sch.
Wladimir Cravero
Mark Gulin
Quark
Toni M
Markus Müller
Nigel222
Mark Gulin
Nigel222
Markus Müller
Markus Müller
Nigel222
Nigel222
phuclv
Quark