Warum dauert die Hardwareteilung so viel länger als die Multiplikation auf einem Mikrocontroller? Auf einem dsPIC benötigt eine Division beispielsweise 19 Zyklen, während die Multiplikation nur einen Taktzyklus benötigt.
Ich habe einige Tutorials durchgearbeitet, darunter Divisionsalgorithmus und Multiplikationsalgorithmus auf Wikipedia. Hier ist meine Argumentation.
Ein Divisionsalgorithmus ist wie eine langsame Divisionsmethode mit Wiederherstellung auf Wikipedia ein rekursiver Algorithmus. Dies bedeutet, dass (Zwischen-) Ergebnisse von 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, wohingegen n
es sich um eine Anzahl von Bits in einer Dividende handelt. 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, welche von Mikrocontrollern verwendet werden können. Wie funktioniert die Multiplikation auf einem Hardware- / Mikrocontroller?
Ich habe einen Dadda-Multiplikator- Algorithmus gefunden, dessen Abschluss nur einen Taktzyklus benötigen soll. Was ich hier jedoch nicht verstehe, ist, dass Daddas Algorithmus in drei Schritten abläuft, wohingegen die Ergebnisse aus Schritt 1 in Schritt 2 usw. verwendet werden. Demnach würde dies mindestens drei Taktzyklen dauern, um fertig zu sein.
quelle
Antworten:
Ein Teiler ordnet einer typischen Hardware viel weniger elegant zu. Nehmen Sie als Beispiel Lattice ICE40 FPGAs.
Vergleichen wir zwei Fälle: diesen 8x8-Bit-16-Bit-Multiplikator:
und dieser Teiler, der 8- und 8-Bit-Operanden auf 8-Bit-Ergebnisse reduziert:
(Ja, ich weiß, ist die Uhr nicht tut nichts)
Eine Übersicht über das generierte Schema beim Mappen des Multiplikators auf ein ICE40-FPGA finden Sie hier und den Teiler hier .
Die Synthesestatistiken von Yosys sind:
multiplizieren
Teilen
Es ist erwähnenswert, dass die Größe des generierten Verilog für einen Multiplikator mit 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 möglicherweise eine Tiefe von 15 hat, wohingegen der Teiler eher wie 50 oder so aussieht. Der kritische Pfad (dh der längste Pfad, der während des Betriebs auftreten kann) definiert die Geschwindigkeit!
Sie können dies sowieso nicht lesen, um sich einen visuellen Eindruck zu verschaffen. Ich denke, die Unterschiede in der Komplexität sind erkennbar. Dies sind Single-Cycle-Multiplikatoren / Dividierer!
Multiplizieren
Multiplizieren Sie auf einem ICE40 (Warnung: ~ 100 Mpixel Bild)
Teilen
( Auf einem ICE40 teilen ) (Warnung: ~ 100 Mpixel Bild)
quelle
Eine langsame Teilung ist von Natur aus iterativ, daher dauert sie in der Regel länger. Es gibt etwas schnellere Algorithmen für langsame Division als die einfachen, die Nachschlagetabellen verwenden. Der SRT-Algorithmus erzeugt zwei Bits pro Zyklus. Ein Fehler in einer solchen Tabelle war die Ursache des berüchtigten Pentium FDIV-Fehlers (ca. 1994). Dann gibt es sogenannte schnelle Divisionsalgorithmen.
Natürlich können Sie im Prinzip einfach eine große Nachschlagetabelle verwenden, um das Produkt oder den Quotienten aus zwei Zahlen zu berechnen und so Ergebnisse in einem einzigen Zyklus zu erhalten. Dies kann jedoch mit zunehmender Anzahl von Bits pro Zahl schnell unpraktisch werden.
quelle
Wir können mehrere Logikschichten pro Taktzyklus haben, aber es gibt eine Grenze, wie viele Logikschichten wir haben können und wie komplex diese Schichten sein können, hängt von unserer Taktgeschwindigkeit und unserem Halbleiterprozess ab.
Die meisten Multiplikationen in Computern verwenden eine Variante der binären Langmultiplikation. Binäre lange Multiplikation beinhaltet
Schauen wir uns also die Implementierung in Hardware an.
Lassen Sie uns also festlegen, wie viele Logikstufen wir für einen 8x8-Multiplikator mit 16-Bit-Ergebnissen benötigen. Der Einfachheit halber nehmen wir an, dass wir nicht versuchen, zu optimieren, dass nicht alle Zwischenergebnisse Bits an allen Positionen aufweisen.
Nehmen wir an, dass ein Volladdierer in zwei "Gate-Stufen" implementiert ist.
Insgesamt also etwa 46 Logikstufen. Die meisten davon werden ausgegeben, um die letzten beiden Zwischenergebnisse zu addieren.
Dies könnte weiter verbessert werden, indem die Tatsache ausgenutzt wird, dass nicht alle Zwischenergebnisse alle vorhandenen Bits aufweisen (das ist im Grunde das, was der Dada-Multiplikator tut), indem ein Carry-Lookahead-Addierer für den letzten Schritt verwendet wird. Durch Addition von 7 zu 3 anstelle von 3 zu 2 (Reduzierung der Anzahl der Stufen zum Preis von mehr Toren und breiteren Toren) usw.
Das sind alles Kleinigkeiten, der wichtige Punkt ist jedoch, dass die Anzahl der Stufen, die benötigt werden, um zwei n-Bit-Zahlen zu multiplizieren und ein 2n-Bit-Ergebnis zu erzeugen, in etwa 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 in etwa proportional zu n im Quadrat.
quelle
Ein Divisionsalgorithmus (tatsächlich ein beliebiger Algorithmus) kann in einem Taktzyklus erstellt werden. Wenn Sie bereit sind, für die zusätzlichen Transistoren und die niedrigere zulässige Taktrate zu bezahlen.
Angenommen, Sie haben eine Reihe von Gattern, die einen Taktzyklus eines vorhandenen Multizyklus-Divisionsalgorithmus implementieren. Um den Algorithmus zu einem einzigen Zyklus zu machen, verwenden Sie mehrere Hardwarestufen (ähnlich der in einer Stufe des Mehrzyklusalgorithmus verwendeten), wobei die Ausgabe einer Stufe die nächste Stufe speist.
Der Grund dafür ist natürlich, dass viele Transistoren verwendet werden. Beispielsweise können für eine 16-Bit-Teilung fast 16 x mehr Transistoren verwendet werden. Wenn auch mehr Stufen von Gattern vorhanden sind, wird die maximal zulässige Taktfrequenz verringert (da mehr Stufen der Ausbreitungsverzögerung vorhanden sind).
quelle
Praktische Divisionsalgorithmen basieren alle auf numerischen Reihen, die zum Quotienten konvergieren.
Es gibt additive Methoden wie Non-Restoring oder SRT, bei denen 2 ^ N zum Quotienten hinzugefügt oder daraus entfernt und der 2 ^ N * -Divisor entsprechend zum Teilrest hinzugefügt oder daraus entfernt wird, bis er gegen Null konvergiert.
Es gibt multiplikative Methoden wie Newton-Raphson oder Goldshmidth, bei denen die Division als Umkehrung der Multiplikation berechnet wird.
Additive Methoden ergeben ein oder mehrere Bits pro Zyklus. Multiplikative Verfahren verdoppeln die Anzahl der Bits für jeden Zyklus, erfordern jedoch eine anfängliche Approximation, 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.
quelle
Dies ist keine elektronische Frage. Bestenfalls handelt es sich um eine Computerfrage, die sich besser an Stack Overflow richtet.
Siehe zum Beispiel hier: Ist die Multiplikation schneller als die Gleitkommadivision?
In Wirklichkeit ist es eine Frage des wirklichen Lebens: Warum dauert die Teilung so viel länger als die Multiplikation?
Welchen würden Sie lieber auf Papier berechnen?
oder
Division dauert länger als Multiplikation, weil es schwieriger ist .
quelle