Design: Arithmetik mit Übertrag

Erstellt am 28. März 2017  ·  7Kommentare  ·  Quelle: WebAssembly/design

(Dies ist eine erweiterte Version des Problems (https://github.com/WebAssembly/spec/issues/446))

Arithmetik mit mehreren Genauigkeiten erfordert eine spezielle Handhabung. Dies ist in irgendeiner Form in allen ISAs verfügbar, aber derzeit nicht in Webasm.

Dafür gibt es grundsätzlich drei Möglichkeiten (wie mir scheint), von denen keine im Kontext des aktuellen Designs besonders schmackhaft ist:

Option 1. Fügen Sie ein spezielles Flag-Register zusammen mit Anweisungen hinzu, die mit diesem Register arithmetisch arbeiten.

Dies ist der traditionelle Ansatz bei Mainstream-Hardware.

Sie erhalten Anweisungen wie

zusätzl

Dadurch werden zwei Zahlen und der Wert des Carry-Flags addiert und das Carry-Flag auf das Ergebnis gesetzt.

Das ist nicht angenehm, weil es ein spezielles Register hinzufügt.

Option 2.
Unterstützung einer Form von 60-Bit-Arithmetik mit 4 Bits für Flags.

Möglichkeit 3.
Unterstützung von Mehrwort-Arithmetik: Die Addition nimmt 3 Argumente und erzeugt 2 Ausgaben.

Dieser Ansatz fügt der bestehenden ISA- und Registerarchitektur den geringsten Schaden zu. Dies lässt sich jedoch nur schwer effizient auf vorhandene Hardware abbilden (nicht alle Hardware-ISAs unterstützen das direkte Laden des Flag-Registers.

Wie auch immer es gemacht wird, Multipräzisionsarithmetik ist ziemlich wichtig und ohne einfache Hardwareunterstützung sehr schwer zu emulieren.

Hilfreichster Kommentar

Gab es Fortschritte bei diesem Thema? Carry und Borrow werden benötigt, um moderne Kryptographie (z. B. SIDH) effizient zu implementieren. Die Addition großer Zahlen ohne ADDC ist um mehrere Faktoren langsamer als mit. Gleiches gilt für Subtraktion und Multiplikation.

Alle 7 Kommentare

Mir scheint, dass es für Option 3 plausible Optimierungen gibt, die dies praktikabel machen würden. Angenommen, {i32,i64}.addc benötigt drei Eingaben, op2 oben, op1 unten, Übertrag unten und erzeugt zwei Ausgaben, Ergebnis oben und Übertrag darunter. Nehmen Sie aus Gründen der Argumentation an, dass der Übertrag immer vom gleichen Typ ist wie die anderen Operanden. Definieren Sie addc nur so, dass das niedrige Bit des Übertrags verwendet wird und dass der nach der Operation verbleibende Übertrag null oder eins ist. Die Dinge sind jetzt zum Beispiel für ein Hinzufügen von mehreren Wörtern vernünftig eingerichtet. In einer entsprechend ausgerollten Schleife sollte ein JIT/Wasm-Compiler wirklich sehen können, dass es sich um den Übertrag handelt, der propagiert wird, und guten Code generieren können. (Und wenn die Schleife nicht entrollt wird, wird der Loop-Overhead die Carry-Extraktion/Einfügung sowieso verwässern.) Ich denke, der verzweigungsfreie Code für die Carry-Extraktion im schlimmsten Fall sollte mov rd, 0; adc rd, 0 sein; zum Einfügen etwa and rc, 1; add rc, ~0 , wobei rc ein Register ist, das einen als Übertrag zu behandelnden Wert enthält.

Auf ARM ist das Konsumieren eines Übertrags von der Erzeugung eines Übertrags getrennt: ADC verbraucht, ADC.S verbraucht und produziert, ADD.S produziert nur. Würden wir all diese Varianten wollen? Und was ist mit Überlauf?

(Es könnte eine vierte Option geben, bei der wir eine Operieren-und-Verzweigen-bei-Bedingung-Operation hinzufügen, die sowohl ein Ergebnis erzeugt als auch zu einem Label verzweigt oder nicht, z. B. würde i32.addc op1 op2 carry L bei Carry Set nach L verzweigen und bei Carry Clear durchfallen und so oder so ein Ergebnis auf dem Stack hinterlassen, aber es scheint im Allgemeinen schwieriger zu verwenden zu sein als die drei von Ihnen vorgeschlagenen Optionen.)

Gibt es jemanden, der bereit ist, sich für diesen Vorschlag einzusetzen? Wir bräuchten eine vorgeschlagene Semantik, binäre Codierung, und ich hätte gerne mindestens einige Anwendungsfälle und eine Implementierung mit Leistungszahlen für diese Anwendungsfälle (vergleiche das aktuelle MVP WebAssembly mit dieser vorgeschlagenen Ergänzung und nativem Code).

Grundsätzlich wäre ich bereit, mich dafür einzusetzen.
Persönliche Veränderungen bedeuten jedoch, dass ich zumindest für die nächsten Monate nur begrenzte Ressourcen habe.
———
Frank McCabe
Leitender Softwarearchitekt
Telefon: 650-740 6673 | E-Mail: [email protected] [email protected]
Startlogik | 450 Lambert Avenue, Palo Alto, CA 94306 | instartlogic.com http://instartlogic.com/

Am 11. Mai 2017 um 10:14 Uhr schrieb JF Bastien [email protected] :

Gibt es jemanden, der bereit ist, sich für diesen Vorschlag einzusetzen? Wir bräuchten eine vorgeschlagene Semantik, binäre Codierung, und ich hätte gerne mindestens einige Anwendungsfälle und eine Implementierung mit Leistungszahlen für diese Anwendungsfälle (vergleiche das aktuelle MVP WebAssembly mit dieser vorgeschlagenen Ergänzung und nativem Code).


Sie erhalten dies, weil Sie den Thread verfasst haben.
Antworten Sie direkt auf diese E-Mail, zeigen Sie sie auf GitHub https://github.com/WebAssembly/design/issues/1021#issuecomment-300856161 an oder schalten Sie den Thread stumm https://github.com/notifications/unsubscribe-auth/ADfCzd9le4ufXm6DSsArpfXCYsGdV7UIks5r40H5gaJpZM4MrKma .

Ich werde wahrscheinlich Zeit haben, mich dem zu widmen, wenn auch nicht sehr viel bis Juni oder so und dann bis in den Herbst hinein. IMO ist diese Funktionalität ziemlich wichtig, und ich denke, das Überlauf-Flag ist genauso wichtig wie das Carry-Flag, allerdings mit unterschiedlichen Anwendungsfällen (Übergang Fixnum -> Bignum der dynamischen Sprachen).

Habe heute mit einigen Mozilla-Leuten darüber gesprochen. Zusammenfassend:

  • Wir wollen hier wahrscheinlich dedizierte Anweisungen, weil das Emulieren des Verhaltens langsam sein wird und wir im Allgemeinen keinen magischen Musterabgleich durchführen möchten, um die Emulation zu erkennen und sie hinter den Kulissen in effizienten Maschinencode umzuwandeln
  • Wir kümmern uns natürlich um Carry/Borrow und Overflow; andere Flaggen TBD
  • Wir kümmern uns mit Sicherheit um das Addieren und Subtrahieren; multiplizieren, dividieren, rotieren (Rotate-Through-Carry ist üblich, aber ist es nützlich für Wasm?) TBD
  • Der häufigste Fall ist, dass wir uns jeweils nur um ein Flag kümmern, und es ist wahrscheinlich angemessen, diesen Fall abzudecken, nicht eine allgemeine Situation, in der "Flags A, B und C erfasst" werden
  • Für Übertrag ist eine Anweisung ausreichend, die immer einen Übertrag verbraucht und immer einen Übertrag erzeugt; Varianten, die verbrauchen, aber nicht produzieren oder umgekehrt, sind nicht erforderlich, und das Fehlen dieser Varianten wird die Ausgabe eines guten Compilers wahrscheinlich nicht beeinträchtigen
  • Wir wollen diese Arbeit mit Daten aus bestehenden guten MP-Bibliotheken (wie Gnu MP) motivieren; Dies können Fakten sein (Bibliothek X hat/hat keine Assembler-Subroutinen oder verwendet Intrinsics, um Flags zu verwenden; sie verwendet die Anweisungen A und B) oder Leistungsdaten (Bibliothek Y kann Assembler-Subroutinen verwenden oder in C emulieren; Leistungsunterschied beträgt N% ) oder Anwendungsfälle (allgemeine Bignum-Arithmetik, Krypto, was mir sonst noch einfällt)
  • Vielleicht möchten wir mit dem Vorschlagen spezifischer Anweisungen warten, bis wir beginnen, Anweisungen zur Erzeugung von Mehrwerten im Allgemeinen zu diskutieren, z. B. Renditen mit mehreren Werten

Gab es Fortschritte bei diesem Thema? Carry und Borrow werden benötigt, um moderne Kryptographie (z. B. SIDH) effizient zu implementieren. Die Addition großer Zahlen ohne ADDC ist um mehrere Faktoren langsamer als mit. Gleiches gilt für Subtraktion und Multiplikation.

Ich denke, wir warten zumindest darauf, dass Multi-Value fertig ist, damit wir eine Operation mit mehr als einem Ergebnis einfach ausdrücken können. Multi-Value ist "fast da".

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

beriberikix picture beriberikix  ·  7Kommentare

mfateev picture mfateev  ·  5Kommentare

JimmyVV picture JimmyVV  ·  4Kommentare

void4 picture void4  ·  5Kommentare

chicoxyzzy picture chicoxyzzy  ·  5Kommentare