Trasmissione in corso…

Questo documento descrive la semantica della trasmissione XLA.

Che cos'è la trasmissione?

La trasmissione è il processo con cui gli array con forme diverse hanno forme compatibili per le operazioni aritmetiche. La terminologia è stata presa in considerazione dalla trasmissione NumPy.

La trasmissione può essere necessaria per le operazioni tra array multidimensionali di diversi ranking o tra array multidimensionali con forme diverse ma compatibili. Considera l'addizione X+v, dove X è una matrice (un array con rango 2) e v è un vettore (un array con rango 1). Per eseguire l'aggiunta in base agli elementi, XLA deve "trasmettere" il vettore v allo stesso ranking della matrice X, replicando v un determinato numero di volte. La lunghezza del vettore deve corrispondere ad almeno una delle dimensioni della matrice.

Ad esempio:

|1 2 3| + |7 8 9|
|4 5 6|

Le dimensioni della matrice sono (2,3) e la dimensione del vettore è (3). Il vettore viene trasmesso replicandolo sulle righe per ottenere:

|1 2 3| + |7 8 9| = |8  10 12|
|4 5 6|   |7 8 9|   |11 13 15|

In NumPy, questa funzionalità è chiamata trasmissione.

Princìpi

Il linguaggio XLA è il più rigoroso ed esplicito possibile, evitando funzionalità "magiche" implicite. Queste funzionalità potrebbero rendere leggermente più semplice la definizione di alcuni calcoli, ma a scapito di più ipotesi integrate nel codice utente che sarà difficile da modificare nel lungo termine. Se necessario, puoi aggiungere funzionalità magiche implicite in wrapper a livello di client.

Per quanto riguarda la trasmissione, XLA richiede specifiche specifiche di trasmissione esplicite sulle operazioni tra array di diversi livelli. È diverso da NumPy, che deduce la specifica, se possibile.

Trasmissione di un array con ranking più basso su un array con ranking più alto

Gli scale possono sempre essere trasmessi su array senza una specifica esplicita delle dimensioni di trasmissione. Un'operazione binaria per elemento tra uno scalare e un array significa applicare l'operazione con lo scalare a ciascun elemento dell'array. Ad esempio, aggiungere uno scalare a una matrice significa produrre una matrice in cui ogni elemento è una somma dello scalare e dell'elemento corrispondente della matrice di input.

|1 2 3| + 7 = |8  9  10|
|4 5 6|       |11 12 13|

La maggior parte delle esigenze di trasmissione può essere acquisita utilizzando una tupla di dimensioni in un'operazione binaria. Quando gli input per l'operazione hanno ranking diversi, questa tupla di trasmissione specifica le dimensioni dell'array con ranking più elevato da abbinare all'array di ranking più basso.

Considera l'esempio precedente. Invece di aggiungere uno scalare a una matrice (2,3), aggiungi un vettore di dimensione (3) a una matrice di dimensioni (2,3). Se non specifichi la trasmissione, questa operazione non è valida. Per richiedere correttamente l'aggiunta matrice-vettore, specifica che la dimensione di trasmissione sia (1), il che significa che la dimensione del vettore viene abbinata alla dimensione 1 della matrice. Nella 2D, se la dimensione 0 rappresenta le righe e la dimensione 1 le colonne, significa che ogni elemento del vettore diventa una colonna di dimensioni corrispondenti al numero di righe della matrice:

|7 8 9| ==> |7 8 9|
            |7 8 9|

Come esempio più complesso, considera l'aggiunta di un vettore di 3 elementi (dimensione (3)) a una matrice 3x3 (dimensioni (3,3)). Per questo esempio, esistono due modi per la trasmissione:

(1) È possibile utilizzare una dimensione di trasmissione pari a 1. Ogni elemento vettoriale diventa una colonna e il vettore viene duplicato per ogni riga della matrice.

|7 8 9| ==> |7 8 9|
            |7 8 9|
            |7 8 9|

(2) È possibile utilizzare una dimensione di trasmissione pari a 0. Ogni elemento vettoriale diventa una riga e il vettore viene duplicato per ogni colonna della matrice.

 |7| ==> |7 7 7|
 |8|     |8 8 8|
 |9|     |9 9 9|

Le dimensioni di trasmissione possono essere una tupla che descrive come una forma di rango più piccola viene trasmessa in una forma di ranking più grande. Ad esempio, dati un cuboide 2x3x4 e una matrice 3x4, una tupla di trasmissione (1,2) corrisponde alle dimensioni 1 e 2 del cuboide.

Questo tipo di trasmissione viene utilizzato nelle operazioni binarie in XlaBuilder, se viene fornito l'argomento broadcast_dimensions. Ad esempio, consulta XlaBuilder::Add. Nel codice sorgente XLA, questo tipo di trasmissione a volte è chiamato "InDim".

Definizione formale

L'attributo broadcasting consente di abbinare un array con ranking inferiore a un array con ranking più alto specificando le dimensioni dell'array con ranking più alto da abbinare. Ad esempio, per un array con dimensioni MxNxPxQ, la corrispondenza a un vettore con dimensione T può essere la seguente:

          MxNxPxQ

dim 3:          T
dim 2:        T
dim 1:      T
dim 0:    T

In ogni caso, T deve essere uguale alla dimensione corrispondente dell'array con ranking più alto. I valori del vettore vengono quindi trasmessi dalla dimensione corrispondente a tutte le altre dimensioni.

Per associare una matrice TxV all'array MxNxPxQ, viene utilizzata una coppia di dimensioni di trasmissione:

          MxNxPxQ
dim 2,3:      T V
dim 1,2:    T V
dim 0,3:  T     V
etc...

L'ordine delle dimensioni nella tupla di trasmissione deve essere l'ordine in cui è previsto che le dimensioni dell'array con ranking inferiore corrispondano a quelle dell'array con ranking superiore. Il primo elemento della tupla specifica quale dimensione nell'array con ranking più alto deve corrispondere alla dimensione 0 nell'array con ranking più basso. Il secondo elemento nella tupla specifica quale dimensione nell'array con ranking più alto deve corrispondere alla dimensione 1 nell'array con ranking più basso e così via. L'ordine delle dimensioni di trasmissione deve essere rigorosamente crescente. Ad esempio, nell'esempio precedente è illegale abbinare V a N e T a P; è illegale anche abbinare V a P e N.

Trasmissione di array con ranking simili con dimensioni degenerate

Un problema correlato è la trasmissione di due array con lo stesso ranking ma dimensioni di dimensioni diverse. Come con NumPy, ciò è possibile solo quando gli array sono compatibili. Due array sono compatibili quando tutte le loro dimensioni sono compatibili. Due dimensioni sono compatibili se:

  • Sono uguali o
  • Una di queste è 1 (dimensione "degenerata")

Quando vengono incontrati due array compatibili, la forma del risultato ha il numero massimo dei due input in ogni indice di dimensione.

Esempi:

  1. (2,1) e (2,3) trasmettono a (2,3).
  2. (1,2,5) e (7,2,5) trasmettono a (7,2,5).
  3. (7,2,5) e (7,1,5) trasmettono a (7,2,5).
  4. (7,2,5) e (7,2,6) non sono compatibili e non possono essere trasmessi.

Si verifica, ed è supportato, un caso speciale in cui ciascuna delle matrici di input ha una dimensione degenerata in un indice diverso. In questo caso, il risultato è un'"operazione esterna": (2,1) e (1,3) broadcast to (2,3). Per altri esempi, consulta la documentazione di NumPy sulla trasmissione.

Composizione della trasmissione

La trasmissione di un array con ranking inferiore a un array con ranking più alto e la trasmissione utilizzando dimensioni degenerate possono essere entrambe eseguite nella stessa operazione binaria. Ad esempio, un vettore di dimensione 4 e una matrice di dimensioni 1 x 2 possono essere sommati utilizzando le dimensioni di trasmissione del valore (0):

|1 2 3 4| + [5 6]    // [5 6] is a 1x2 matrix, not a vector.

Innanzitutto, il vettore viene trasmesso fino al ranking 2 (matrice) utilizzando le dimensioni di trasmissione. Il valore singolo (0) nelle dimensioni di trasmissione indica che la dimensione zero del vettore corrisponde alla dimensione zero della matrice. Questo produce una matrice di dimensione 4 x M in cui il valore M viene scelto in modo che corrisponda alla dimensione corrispondente nell'array 1 x 2. Quindi si produce una matrice 4x2:

|1 1| + [5 6]
|2 2|
|3 3|
|4 4|

A questo punto, "degenerazione della trasmissione delle dimensioni" trasmette la dimensione zero della matrice 1 x 2 in modo che corrisponda alla dimensione della dimensione corrispondente del lato destro:

|1 1| + |5 6|     |6  7|
|2 2| + |5 6|  =  |7  8|
|3 3| + |5 6|     |8  9|
|4 4| + |5 6|     |9 10|

Un esempio più complicato è una matrice di dimensioni 1 x 2 aggiunta a un array di dimensioni 4 x 3 x 1 utilizzando le dimensioni di trasmissione di (1, 2). Innanzitutto, la matrice 1 x 2 viene trasmessa fino al rango 3 utilizzando le dimensioni di trasmissione per produrre un array Mx1 x 2 intermedio in cui la dimensione M è determinata dalla dimensione dell'operando più grande (l'array 4 x 3 x 1) che produce un array intermedio 4 x 1 x 2. La M si trova alla dimensione 0 (la dimensione più a sinistra) perché le dimensioni 1 e 2 sono mappate alle dimensioni della matrice 1 x 2 originale così come le dimensioni di trasmissione (1, 2). Questo array intermedio può essere aggiunto alla matrice 4 x 3 x 1 utilizzando la trasmissione di dimensioni degenerate per produrre un risultato dell'array 4 x 3 x 2.