Hat ein 16-Bit- oder 36-Bit-Computerbefehlssatz jemals 4x4- oder 6x6-Bitmatrixoperationen enthalten?

Sep 27 2020

Die 64-Bit- MMIX-Architektur von Donald Knuth enthält mehrere neuartige Anweisungen, die matrixweise auf einer 8x8-Quadratmatrix ( MOR, MXOR) arbeiten.

(MMIX hat auch Anweisungen wie diese BDIF, die vektorweise mit 8x 8-Bit-Ganzzahlen arbeiten, was weniger neu ist; x86 macht das ganz gut.)

Die Behandlung Ihres 64-Bit-Wortes als quadratische Matrix ist nur möglich, wenn die Wortgröße ein perfektes Quadrat ist.

Früher gab es Computer mit einer Wortlänge von 36 Bit . Das ist bekanntlich genug, um 6x 6-Bit-Zeichen (vor ASCII) in einem einzigen Wort zu speichern. Hat jemals ein historischer 36-Bit-Computer Operationen angeboten, die am besten durch das Lesen von Maschinenwörtern als 6x6-Matrizen verstanden wurden?

Wie wäre es mit einem historischen 16-Bit-Computer?

Neben komplizierten Anweisungen wie MMIXs MORund wäre MXORdas einfachste Beispiel für eine "Matrixoperation" in dem Sinne, wie ich meine, eine unäre TRANSPOSEOperation:

TRANSPOSE(1001'1010'1010'1011) = 1111'0000'0111'1001
TRANSPOSE(1001'0010'1011'0100) = 1010'0001'0110'1010

Antworten

6 mcleod_ideafix Sep 27 2020 at 03:17

Ich weiß nicht, ob es sich um einen historischen 16-Bit-Computer handelt, aber es gab eine Reihe von 80287-Klonen. Einer von ihnen von IIT fügte einen F4x4-Befehl hinzu, der auf dem gesamten FP-Stapel arbeitete, um Matrixoperationen auszuführen (der IIT-Chip hatte nicht einen, sondern vier Stapel mit jeweils acht FPU-Registern).

Ein Freund von mir hatte damals einen dieser Coprozessoren und es kam mit einem Demo-Programm, das einen Geschwindigkeitstest dieser F4x4-Anweisung zeigte. Das Leafsheet, das als Anpassungs- und Benutzerhandbuch diente, erwähnte diese Funktion ebenfalls.

Die einzigen Informationen, die ich bisher gefunden habe, stammen aus der Datei COPRO16A.TXT von Norbert Juffa . Auszüge aus diesem Dokument sind:

Der IIT 2C87 bietet zusätzliche Funktionen, die auf keinem anderen 287-Chip verfügbar sind [38]. Es verfügt über 24 vom Benutzer zugängliche Gleitkommaregister, die in drei Registerbänken organisiert sind. Zusätzliche Anweisungen (FSBP0, FSBP1, FSBP2) ermöglichen den Wechsel von einer Bank zu einer anderen. (Übertragungen zwischen Registern in verschiedenen Bänken werden jedoch nicht unterstützt, sodass diese Funktion für sich genommen nur von begrenztem Nutzen ist. Außerdem scheint es nur ein Statusregister zu geben (das den oberen Stapelzeiger enthält), sodass es manuell geladen und gespeichert werden muss beim Umschalten zwischen Banken mit einer anderen Anzahl verwendeter Register [40]). Der Hauptzweck der Registerbank besteht darin, den vierten zusätzlichen Befehl des 2C87 (F4X4) zu unterstützen, der eine vollständige Multiplikation einer 4x4-Matrix mit einem 4x1-Vektor ausführt, eine Operation, die in 3D-Grafikanwendungen üblich ist [39].Die eingebaute Multiplikationsmatrix beschleunigt diesen Vorgang im Vergleich zu einer nach Angaben des Herstellers programmierten Lösung um den Faktor 6 bis 8 [38]. Tests zeigen, dass die Beschleunigung tatsächlich in diesem Bereich liegt [40]. Für den 3C87 habe ich die Ausführungszeit von F4X4 mit etwa 280 Taktzyklen gemessen. Die Ausführungszeit auf dem 2C87 sollte etwas länger sein - ich schätze, dass sie aufgrund des höheren CPU-NDP-Kommunikationsaufwands bei der Befehlsausführung in 286/287 Systemen (~ 45-50 Taktzyklen) im Vergleich zu 386/387 bei etwa 310 Taktzyklen liegt Systeme (~ 16-20 Taktzyklen). So wünschenswert der F4X4-Befehl auch erscheinen mag, es gibt nur sehr wenige Anwendungen, die ihn verwenden, wenn zur Laufzeit ein IIT-Coprozessor erkannt wird (darunter der Silver Screen von Schroff Development und der Fast-CAD 3-D von Evolution Computing [25]). .

Und eine Routine, die zeigt, wie man die F4x4-Anweisung verwendet:

  ;---------------------------------------------------------------------
  ;
  ; IIT_MUL_4x4 multiplicates a four-by-four matrix by an array of four
  ; dimensional vectors. This operation is needed for 3D transformations
  ; in graphics data processing. There are arrays for each component of
  ; a vector.  Thus there is an array containing all the x components,
  ; another containing all the y components and so on. Each component is
  ; an 8 byte IEEE floating-point number. Two indices into the array of
  ; vectors are given. The first is the index of the vector that will be
  ; processed first, the second is the index of the vector processed
  ; last. This subroutine uses the special instructions only available
  ; on IIT coprocessors to provide fast matrix multiply capabilities.
  ; So make sure to use it only on IIT coprocessors.
  ;
  ;---------------------------------------------------------------------

  IIT_MUL_4x4   PROC    NEAR

        AddrX   EQU DWORD PTR [BP+24] ; address of X component array
        AddrY   EQU DWORD PTR [BP+20] ; address of Y component array
        AddrZ   EQU DWORD PTR [BP+16] ; address of Z component array
        AddrW   EQU DWORD PTR [BP+12] ; address of W component array
        AddrT   EQU DWORD PTR [BP+8]  ; addr. of 4x4 transf. matrix
        F       EQU WORD  PTR [BP+6]  ; first vector to process
        K       EQU WORD  PTR [BP+4]  ; last vector to process
        RetAddr EQU WORD  PTR [BP+2]  ; return address saved by call
        SavdBP  EQU WORD  PTR [BP+0]  ; saved frame pointer
        SavdDS  EQU WORD  PTR [BP-2]  ; caller's data segment
        Ctrl87  EQU WORD  PTR [BP-4]  ; caller's 80x87 control word

        PUSH    BP                    ; save TURBO-Pascal frame ptr
        MOV     BP, SP                ; new frame pointer
        PUSH    DS                    ; save TURBO-Pascal data seg.
        SUB     SP, 2                 ; make local variabe
        FSTCW   [Ctrl87]              ; save 80x87 ctrl word
        LES     SI, AddrT             ; ptr to transformation matrix
        FINIT                         ; initialize coprocessor
        FSBP2                         ; set register bank 2
        FLD     QWORD PTR ES:[SI]     ; load a[0,0]
        FLD     QWORD PTR ES:[SI+32]  ; load a[1,0]
        FLD     QWORD PTR ES:[SI+64]  ; load a[2,0]
        FLD     QWORD PTR ES:[SI+96]  ; load a[3,0]
        FLD     QWORD PTR ES:[SI+8]   ; load a[0,1]
        FLD     QWORD PTR ES:[SI+40]  ; load a[1,1]
        FLD     QWORD PTR ES:[SI+72]  ; load a[2,1]
        FLD     QWORD PTR ES:[SI+104] ; load a[3,1]
        FINIT                         ; initialize coprocessor
        FSBP1                         ; set register bank 1
        FLD     QWORD PTR ES:[SI+16]  ; load a[0,2]
        FLD     QWORD PTR ES:[SI+48]  ; load a[1,2]
        FLD     QWORD PTR ES:[SI+80]  ; load a[2,2]
        FLD     QWORD PTR ES:[SI+112] ; load a[3,2]
        FLD     QWORD PTR ES:[SI+24]  ; load a[0,3]
        FLD     QWORD PTR ES:[SI+56]  ; load a[1,3]
        FLD     QWORD PTR ES:[SI+88]  ; load a[2,3]
        FLD     QWORD PTR ES:[SI+120] ; load a[3,3]

                                      ; transformation matrix loaded

        MOV     AX, F                 ; index of first vector
        MOV     DX, K                 ; index of last vector

        MOV     BX, AX                ; index 1st vector to process
        MOV     CL, 3                 ; component has 8 (2**3) bytes
        SHL     BX, CL                ; compute offset into arrays

        FINIT                         ; initialize coprocessor
        FSBP0                         ; set register bank 0

  $mat_loop:LES SI, AddrW ; addr. of W component array FLD QWORD PTR ES:[SI+BX] ; W component current vector LES SI, AddrZ ; addr. of Z component array FLD QWORD PTR ES:[SI+BX] ; Z component current vector LES SI, AddrY ; addr. of Y component array FLD QWORD PTR ES:[SI+BX] ; Y component current vector LES SI, AddrX ; addr. of X component array FLD QWORD PTR ES:[SI+BX] ; X component current vector F4X4 ; mul 4x4 matrix by 4x1 vector INC AX ; next vector MOV DI, AX ; next vector SHL DI, CL ; offset of vector into arrays FSTP QWORD PTR ES:[SI+BX] ; store X comp. of curr. vect. LES SI, AddrY ; address of Y component array FSTP QWORD PTR ES:[SI+BX] ; store Y comp. of curr. vect. LES SI, AddrZ ; address of Z component array FSTP QWORD PTR ES:[SI+BX] ; store Z comp. of curr. vect. LES SI, AddrW ; address of W component array FSTP QWORD PTR ES:[SI+BX] ; store W comp. of curr. vect. MOV BX, DI ; ofs nxt vect. in comp. arrays CMP AX, DX ; nxt vector past upper bound? JLE $mat_loop             ; no, transform next vector
        FLDCW   [Ctrl87]              ; restore orig 80x87 ctrl word

        ADD      SP, 2                ; get rid of local variable
        POP      DS                   ; restore TP data segment
        POP      BP                   ; restore TP frame pointer
        RET      24                   ; pop parameters and return
  IIT_MUL_4x4   ENDP

  CODE      ENDS

  END
5 Chromatix Sep 27 2020 at 05:42

Ich denke, die große Frage, die Sie hier stellen müssen, lautet: Wofür wäre eine solche Anweisung nützlich gewesen? Einzelbit-Datentypen passen normalerweise nicht zu Matrixoperationen.

Ich habe mir einige Beispiele angesehen, in denen die MMIX-Anweisungen verwendet werden, und sie scheinen angesichts der Komplexität der Hardware nicht sehr überzeugend zu sein. Wenn Sie beispielsweise eine ROLAnweisung wünschen , können Sie SHLder Implementierung einer Anweisung einige Tore hinzufügen und alle Gymnastik vermeiden, die erforderlich ist, um sie mit einer MORAnweisung zu emulieren . Ein weiteres Beispiel besteht darin, eine schmale Zeichenfolge (z. B. ASCII) in eine breitere (z. B. UTF-16) zu unterteilen, was mir als nicht häufig genug erscheint, um die Verwendung von etwas Klügerem als der offensichtlichen Skalarschleife zu rechtfertigen.

Die besten mir bekannten Beispiele für diese Art von Operation stammen von relativ neuen CPUs mit SIMD-Einheiten wie ARM NEON (eine 32-Bit-Architektur mit 64-Bit- und 128-Bit-SIMD-Registern). Diese umfassen häufig sowohl "horizontale" (z. B. Summe aller Elemente in einem einzelnen Register) als auch "vertikale" (z. B. zwei Register elementweise multiplizieren und zu einem dritten akkumulieren) Operationen, die verwendet werden können, um die Matrixarithmetik durch Kombinieren von a effizient zu unterstützen relativ kleine Anzahl von Anweisungen. Es gibt auch Anweisungen zum Verschachteln und Aufheben der Verschachtelung von Daten (auch bekannt als Zip- und Unzip-Operationen), die zum Transponieren von Matrizen sehr nützlich sein können.