Die meisten Hardware-Multiplikations- und Divisionsalgorithmen können die hohen und niedrigen Wörter eines Produkts aus zwei ganzen Zahlen oder sowohl den Quotienten als auch den Rest der Division zweier ganzer Zahlen gleichzeitig berechnen. In großen RISC-ISAs gibt es viele verschiedene Ansätze zur ganzzahligen Multiplikation und Division. (In diesem Beitrag betrachte ich nur Integer- und keine Fließkomma-Mathematik.)
SMULL
und UMULL
, die in v3M eingeführt wurden. Diese speichern das hohe und das niedrige Wort des Produkts zweier 32-Bit-Ganzzahlen in verschiedenen 32-Bit-Registern. Es hat auch viele andere Varianten von Multiplikationsanweisungen. Es berechnet jedoch nicht den Rest einer Division.SMULL
und UMULL
speichert das 64-Bit-Produkt zweier 32-Bit-Ganzzahlen in einem 64-Bit-Register. Es hat per se keinen 64-Bit-Multiplikationsbefehl . Um zu multiplizieren, führen Sie eine Multiplikations-Addierung durch, die das Nullregister addiert. Es gibt eine ganzzahlige Division, aber keinen ganzzahligen Modul.MULH
, MUL
, DIV
und REM
, aber das RISC-V Instruction Set Manual empfiehlt, dass Mikroarchitekturen verwendet werden, wenn a von a mit denselben Quelloperanden oder a von a mit denselben Quelloperanden MULH
gefolgt wird kann diese Operationen zu einer einzigen Operation verschmelzen, anstatt zwei getrennte auszuführen.MUL
DIV
REM
Es ist definitiv möglich, das vollständige Ergebnis einer Multiplikation oder Division und Rest gleichzeitig zu berechnen. Mehrere RISC ISAs haben dazu eine Anweisung! Theoretisch könnten Sie, wenn Sie nur ein Ergebnis wünschen, das Ziel des anderen auf das Nullregister setzen. Warum hat dann kein RISC-ISA, den ich mir angesehen habe, eine Anweisung, sowohl den Quotienten als auch den Rest in separaten Mehrzweckregistern zu speichern, und warum hat der eine ISA, den ich gefunden habe, der dies für die hohen und niedrigen Wörter eines Produkts tut, ARM A32, lassen Sie es in der nächsten großen Revision fallen?
Mich interessiert besonders, warum die frühen RISC-Chips Mitte der 80er diese Designwahl getroffen haben. SPARC V8 hatte kein Befehlsformat mit zwei Quell- und zwei Zielregistern und wollte möglicherweise seinen Decoder nicht mit einem anderen Format verkomplizieren. MIPS I: Abstriche machen, um komplexere Anweisungen in eine klassische RISC-Pipeline zu integrieren?
Aber ich frage mich auch, warum sich moderne RISC-Architekturen davon entfernt haben. Ich vermute, ARM A64 macht das so, weil Multiplizieren-Addieren mit fester Genauigkeit für die Multimedia-Decodierung nützlich ist, mit weniger relativem Overhead, je mehr Bits Sie multiplizieren, und sobald Sie das haben, ist es sinnvoll, die Schaltungen für die Multiplikation wiederzuverwenden ( füge einfach 0 hinzu). Aber die RISC-V-Dokumentation schlägt vor, dass der Kern eine einzige Operation haben sollte, die beide Ergebnisse berechnet, also warum nicht in einem RISC-Design diese in der ISA verfügbar machen?
Gibt es irgendwelche veröffentlichten Artikel, die sich mit diesem Thema befassen? Oder haben die Designer dieser Architekturen jemals ihre Gründe dafür erklärt?
Im Allgemeinen sind die geschäftlichen Anforderungen an Prozessordesigns darauf ausgerichtet, entweder synthetische Benchmarks oder reale Anwendungs-Workloads zu erfüllen . Funktionen, die keines davon ansprechen, sind schwerer zu verkaufen und werden daher eher ausgelassen.
In den 80er Jahren war der Dhrystone-Benchmark sehr beliebt. Normalerweise würde dies in einer Hochsprache dargestellt, normalerweise enthält C. Dhrystone keine Restoperationen! Designer, die auf einen hohen Dhrystone-Score abzielen, könnten also die Restoperation weglassen, um die Zykluszeit um einige Pikosekunden zu verkürzen.
Die meisten Hochsprachen haben separate arithmetische Operatoren für Quotient und Rest, nur sehr wenige bieten standardisierte Operationen, um beides aus einer einzigen Operation zu erhalten (teilweise, weil C und FORTRAN keine nativen Tupel haben!). Bis vor kurzem waren Compiler nicht besonders gut darin, Optimierungen zu erkennen, die es ihnen ermöglichen würden, zwei Operationen in eine Anweisung zu falten.
Wenn wir uns die Art von arithmetischer Arbeit ansehen, für die Prozessoren optimiert wurden , kümmern sie sich tendenziell nicht um Reste. Die großen Beispiele sind FFT und Matrixmultiplikation für lineare Algebra. Aus diesem Grund neigen Prozessoren dazu, Anweisungen zum Multiplizieren und Akkumulieren und SIMD-Anweisungen zu haben.
%
Operationen erforderte. Die C-Standardbibliothek hat div()
und ldiv()
, die zweigliedrige Strukturen zurückgeben und Hardware nutzen sollen, die sowohl den Quotienten als auch den Rest auf einmal findet. Compiler können diese Optimierung jetzt normalerweise automatisch durchführen, diese Anweisungen sind (wie bereits erwähnt) weniger verbreitet und /
wurden %
so gut spezifiziert wie div()
und ldiv()
seit C99. Es ist nicht mehr wirklich ein Vorteil, sie zu verwenden, und ich frage mich, wie viel Code es jemals getan hat.mod
langsam war, und mod
langsam, weil Algorithmen wie Good-Thomas nicht als wichtig angesehen wurden?
Neil_DE
Davislor
jonk
jonk
Davislor
jonk
Toni M
Oldtimer
Oldtimer
Davislor