In diesem Dokument werden die Broadcasting-Semantiken von XLA beschrieben.
Was ist Broadcasting?
Beim Broadcasting werden Arrays mit unterschiedlichen Formen so angepasst, dass sie für arithmetische Operationen kompatibel sind. Die Terminologie stammt aus NumPy-Broadcasting.
Broadcasting kann für Operationen zwischen mehrdimensionalen Arrays mit unterschiedlichen Rängen oder zwischen mehrdimensionalen Arrays mit unterschiedlichen, aber kompatiblen Formen erforderlich sein. Betrachten wir die Addition X+v, wobei X eine Matrix (ein Array mit 2 Dimensionen) und v ein Vektor (ein Array mit 1 Dimension) ist. Für die elementweise Addition muss XLA den Vektor v auf die gleiche Anzahl von Dimensionen wie die Matrix X übertragen, indem v eine bestimmte Anzahl von Malen repliziert wird. Die Länge des Vektors muss mit mindestens einer der Dimensionen der Matrix übereinstimmen.
Beispiel:
|1 2 3| + |7 8 9|
|4 5 6|
Die Dimensionen der Matrix sind (2,3) und die des Vektors (3). Der Vektor wird durch Replizieren über Zeilen übertragen, um Folgendes zu erhalten:
|1 2 3| + |7 8 9| = |8 10 12|
|4 5 6| |7 8 9| |11 13 15|
In NumPy wird dies als Broadcasting bezeichnet.
Grundsätze
Die XLA-Sprache ist so streng und explizit wie möglich und vermeidet implizite „magische“ Funktionen. Solche Funktionen können die Definition einiger Berechnungen etwas vereinfachen, gehen jedoch auf Kosten von mehr Annahmen im Nutzercode, die langfristig schwer zu ändern sind. Bei Bedarf können implizite magische Funktionen in Wrappern auf Clientebene hinzugefügt werden.
In Bezug auf Broadcasting erfordert XLA explizite Broadcasting-Spezifikationen für Operationen zwischen Arrays mit unterschiedlichen Rängen. Das unterscheidet sich von NumPy, wo die Spezifikation nach Möglichkeit abgeleitet wird.
Broadcasten eines Arrays mit niedrigerer Dimension auf ein Array mit höherer Dimension
Skalare können immer über Arrays hinweg übertragen werden, ohne dass die Broadcast-Dimensionen explizit angegeben werden müssen. Eine elementweise binäre Operation zwischen einem Skalar und einem Array bedeutet, dass die Operation mit dem Skalar auf jedes Element im Array angewendet wird. Wenn Sie beispielsweise einer Matrix einen Skalar hinzufügen, erhalten Sie eine Matrix, in der jedes Element die Summe aus dem Skalar und dem entsprechenden Element der Eingabematrix ist.
|1 2 3| + 7 = |8 9 10|
|4 5 6| |11 12 13|
Die meisten Broadcast-Anforderungen können durch die Verwendung eines Tupels von Dimensionen für eine binäre Operation abgedeckt werden. Wenn die Eingaben für den Vorgang unterschiedliche Ränge haben, gibt dieses Broadcasting-Tupel an, welche Dimension(en) im höherdimensionalen Array mit dem niedrigdimensionalen Array übereinstimmen sollen.
Sehen Sie sich das vorherige Beispiel an. Anstatt einer (2,3)-Matrix einen Skalar hinzuzufügen, fügen Sie einer (2,3)-Matrix einen Vektor der Dimension 3 hinzu. Ohne Angabe von Broadcasting ist dieser Vorgang ungültig. Wenn Sie die Matrix-Vektor-Addition korrekt anfordern möchten, geben Sie für die Broadcast-Dimension den Wert (1) an. Das bedeutet, dass die Dimension des Vektors mit Dimension 1 der Matrix übereinstimmt. In 2D, wenn Dimension 0 für Zeilen und Dimension 1 für Spalten steht, bedeutet das, dass jedes Element des Vektors zu einer Spalte wird, deren Größe der Anzahl der Zeilen in der Matrix entspricht:
|7 8 9| ==> |7 8 9|
|7 8 9|
Ein komplexeres Beispiel: Sie möchten einen Vektor mit drei Elementen (Dimension (3)) zu einer 3x3-Matrix (Dimensionen (3,3)) hinzufügen. In diesem Beispiel gibt es zwei Möglichkeiten, wie die Übertragung erfolgen kann:
1. Es kann eine Broadcasting-Dimension von 1 verwendet werden. Jedes Vektorelement wird zu einer Spalte und der Vektor wird für jede Zeile in der Matrix dupliziert.
|7 8 9| ==> |7 8 9|
|7 8 9|
|7 8 9|
2. Es kann eine Broadcasting-Dimension von 0 verwendet werden. Jedes Vektorelement wird zu einer Zeile und der Vektor wird für jede Spalte in der Matrix dupliziert.
|7| ==> |7 7 7|
|8| |8 8 8|
|9| |9 9 9|
Die Broadcasting-Dimensionen können ein Tupel sein, das beschreibt, wie eine Form mit weniger Dimensionen in eine Form mit mehr Dimensionen übertragen wird. Wenn Sie beispielsweise einen 2 × 3 × 4-Quader und eine 3 × 4-Matrix haben, bedeutet ein Broadcasting-Tupel (1, 2), dass die Matrix mit den Dimensionen 1 und 2 des Quaders abgeglichen wird.
Diese Art von Broadcast wird in den binären Operationen in XlaBuilder verwendet, wenn das broadcast_dimensions-Argument angegeben ist. Ein Beispiel finden Sie unter XlaBuilder::Add.
Im XLA-Quellcode wird diese Art von Broadcasting manchmal als „InDim“-Broadcasting bezeichnet.
Formale Definition
Mit dem Attribut „Broadcasting“ kann ein Array mit niedrigerer Dimension an ein Array mit höherer Dimension angepasst werden. Dazu wird angegeben, welche Dimensionen des Arrays mit höherer Dimension angepasst werden sollen. Für ein Array mit den Dimensionen MxNxPxQ kann ein Vektor mit der Dimension T beispielsweise so abgeglichen werden:
MxNxPxQ
dim 3: T
dim 2: T
dim 1: T
dim 0: T
In jedem Fall muss T gleich der entsprechenden Dimension des höherdimensionalen Arrays sein. Die Werte des Vektors werden dann von der übereinstimmenden Dimension auf alle anderen Dimensionen übertragen.
Um eine TxV-Matrix dem MxNxPxQ-Array zuzuordnen, wird ein Paar von Broadcasting-Dimensionen verwendet:
MxNxPxQ
dim 2,3: T V
dim 1,2: T V
dim 0,3: T V
etc...
Die Reihenfolge der Dimensionen im Broadcasting-Tupel muss der Reihenfolge entsprechen, in der die Dimensionen des Arrays mit niedrigerer Dimension mit den Dimensionen des Arrays mit höherer Dimension übereinstimmen sollen. Das erste Element im Tupel gibt an, welche Dimension im höherdimensionalen Array mit Dimension 0 im niedrigerdimensionalen Array übereinstimmen muss. Das zweite Element im Tupel gibt an, welche Dimension im höherdimensionalen Array mit Dimension 1 im niedrigdimensionalen Array übereinstimmen muss usw. Die Reihenfolge der Broadcast-Dimensionen muss streng aufsteigend sein. Im vorherigen Beispiel ist es beispielsweise unzulässig, V mit N und T mit P abzugleichen. Es ist auch unzulässig, V sowohl mit P als auch mit N abzugleichen.
Broadcasting von Arrays ähnlicher Dimensionen mit degenerierten Dimensionen
Ein ähnliches Problem ist das Broadcasting von zwei Arrays mit derselben Anzahl von Dimensionen, aber unterschiedlichen Dimensionsgrößen. Wie bei NumPy ist dies nur möglich, wenn die Arrays kompatibel sind. Zwei Arrays sind kompatibel, wenn alle ihre Dimensionen kompatibel sind. Zwei Dimensionen sind kompatibel, wenn:
- Sie sind gleich.
- Eine davon ist 1 (eine „entartete“ Dimension).
Wenn zwei kompatible Arrays gefunden werden, hat die Ergebnisform an jedem Dimensionsindex das Maximum der beiden Eingaben.
Beispiele:
- (2,1) und (2,3) werden an (2,3) übertragen.
- (1,2,5) und (7,2,5) werden auf (7,2,5) übertragen.
- (7,2,5) und (7,1,5) werden auf (7,2,5) übertragen.
- (7,2,5) und (7,2,6) sind inkompatibel und können nicht übertragen werden.
Ein Sonderfall, der ebenfalls unterstützt wird, tritt ein, wenn jeder der Eingabearrays eine degenerierte Dimension an einem anderen Index hat. In diesem Fall ist das Ergebnis eine „äußere Operation“: (2,1) und (1,3) werden auf (2,3) übertragen. Weitere Beispiele finden Sie in der NumPy-Dokumentation zum Broadcasting.
Zusammensetzung der Übertragung
Die Übertragung eines Arrays mit niedrigerer Dimension auf ein Array mit höherer Dimension und die Übertragung mit degenerierten Dimensionen können beide im selben binären Vorgang ausgeführt werden. Ein Vektor der Größe 4 und eine Matrix der Größe 1 × 2 können beispielsweise mit Broadcast-Dimensionen des Werts (0) addiert werden:
|1 2 3 4| + [5 6] // [5 6] is a 1x2 matrix, not a vector.
Zuerst wird der Vektor mithilfe der Broadcast-Dimensionen auf zwei Dimensionen (Matrix) erweitert. Der einzelne Wert (0) in den Broadcast-Dimensionen gibt an, dass Dimension 0 des Vektors mit Dimension 0 der Matrix übereinstimmt. Daraus ergibt sich eine Matrix der Größe 4 × M, wobei der Wert M so gewählt wird, dass er der entsprechenden Dimensionsgröße im 1 × 2-Array entspricht. Es wird also eine 4 × 2-Matrix erstellt:
|1 1| + [5 6]
|2 2|
|3 3|
|4 4|
Anschließend wird die Dimension 0 der 1×2-Matrix durch „Broadcasting degenerierter Dimensionen“ so angepasst, dass sie der entsprechenden Dimension der rechten Seite entspricht:
|1 1| + |5 6| |6 7|
|2 2| + |5 6| = |7 8|
|3 3| + |5 6| |8 9|
|4 4| + |5 6| |9 10|
Ein komplizierteres Beispiel ist eine Matrix der Größe 1 × 2, die einem Array der Größe 4 × 3 × 1 mit Broadcast-Dimensionen von (1, 2) hinzugefügt wird. Zuerst wird die 1×2-Matrix mithilfe der Broadcast-Dimensionen auf 3 Dimensionen erweitert, um ein Zwischen-Array mit den Dimensionen M×1×2 zu erstellen. Die Größe der Dimension M wird durch die Größe des größeren Operanden (des 4×3×1-Arrays) bestimmt, sodass ein Zwischen-Array mit den Dimensionen 4×1×2 entsteht. Die M befindet sich in Dimension 0 (der Dimension ganz links), da die Dimensionen 1 und 2 den Dimensionen der ursprünglichen 1 × 2-Matrix zugeordnet sind, da die Broadcast-Dimensionen (1, 2) sind. Dieses Zwischen-Array kann der 4×3×1-Matrix durch Broadcasting von degenerierten Dimensionen hinzugefügt werden, um ein 4×3×2-Array-Ergebnis zu erhalten.