Cette page a été traduite par l'API Cloud Translation.
Switch to English

Sémantique de diffusion

Ce document décrit le fonctionnement de la sémantique de diffusion dans XLA.

Qu'est-ce que la radiodiffusion?

La diffusion est le processus de création de tableaux de différentes formes ayant des formes compatibles pour les opérations arithmétiques. La terminologie est empruntée à la diffusion Numpy.

La diffusion peut être nécessaire pour des opérations entre des réseaux multidimensionnels de rangs différents, ou entre des réseaux multidimensionnels de formes différentes mais compatibles. Considérons l'addition X+vX est une matrice (un tableau de rang 2) et v est un vecteur (un tableau de rang 1). Pour effectuer une addition élément par élément, XLA a besoin de "diffuser" le vecteur v au même rang que la matrice X , en répliquant v un certain nombre de fois. La longueur du vecteur doit correspondre à au moins une des dimensions de la matrice.

Par exemple:

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

Les dimensions de la matrice sont (2,3), les vecteurs sont (3). Le vecteur est diffusé en le répliquant sur des lignes pour obtenir:

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

Dans Numpy, cela s'appelle la diffusion .

Des principes

Le langage XLA est aussi strict et explicite que possible, évitant les fonctionnalités implicites et «magiques». De telles fonctionnalités peuvent rendre certains calculs un peu plus faciles à définir, au prix de plus d'hypothèses intégrées dans le code utilisateur qu'il sera difficile de changer à long terme. Si nécessaire, des fonctionnalités implicites et magiques peuvent être ajoutées dans des wrappers au niveau du client.

En ce qui concerne la diffusion, des spécifications de diffusion explicites sur les opérations entre des tableaux de rangs différents sont nécessaires. Ceci est différent de Numpy, qui déduit la spécification lorsque cela est possible.

Diffusion d'un tableau de rang inférieur sur un tableau de rang supérieur

Les scalaires peuvent toujours être diffusés sur des tableaux sans spécification explicite des dimensions de diffusion. Une opération binaire élément par élément entre un scalaire et un tableau signifie appliquer l'opération avec le scalaire pour chaque élément du tableau. Par exemple, ajouter un scalaire à une matrice signifie produire une matrice dont chaque élément est une somme du scalaire avec l'élément de la matrice d'entrée correspondant.

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

La plupart des besoins de diffusion peuvent être capturés en utilisant un tuple de dimensions sur une opération binaire. Lorsque les entrées de l'opération ont des rangs différents, ce tuple de diffusion spécifie la ou les dimensions du tableau de rang supérieur à faire correspondre avec le tableau de rang inférieur .

Prenons l'exemple précédent, au lieu d'ajouter un scalaire à une matrice (2,3), ajoutez un vecteur de dimension (3) à une matrice de dimensions (2,3). Sans spécifier la diffusion, cette opération n'est pas valide. Pour demander correctement l'ajout de matrice-vecteur, spécifiez la dimension de diffusion à (1), ce qui signifie que la dimension du vecteur correspond à la dimension 1 de la matrice. En 2D, si la dimension 0 est considérée comme des lignes et la dimension 1 comme des colonnes, cela signifie que chaque élément du vecteur devient une colonne d'une taille correspondant au nombre de lignes de la matrice:

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

Comme exemple plus complexe, envisagez d'ajouter un vecteur à 3 éléments (dimension (3)) à une matrice 3x3 (dimensions (3,3)). Il y a deux manières de diffuser pour cet exemple:

(1) Une dimension de diffusion de 1 peut être utilisée. Chaque élément vectoriel devient une colonne et le vecteur est dupliqué pour chaque ligne de la matrice.

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

(2) Une dimension de diffusion de 0 peut être utilisée. Chaque élément vectoriel devient une ligne et le vecteur est dupliqué pour chaque colonne de la matrice.

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

Les dimensions de diffusion peuvent être un tuple qui décrit comment une forme de rang plus petite est diffusée dans une forme de rang plus grande. Par exemple, étant donné un cuboïde 2x3x4 et une matrice 3x4, un tuple de diffusion (1,2) signifie faire correspondre la matrice aux dimensions 1 et 2 du cuboïde.

Ce type de diffusion est utilisé dans les opérations binaires de XlaBuilder , si l'argument broadcast_dimensions est donné. Par exemple, consultez XlaBuilder :: Add . Dans le code source XLA, ce type de diffusion est parfois appelé diffusion "InDim".

Définition formelle

L'attribut de diffusion permet de faire correspondre un tableau de rang inférieur à un tableau de rang supérieur, en spécifiant les dimensions du tableau de rang supérieur à mettre en correspondance. Par exemple, pour un tableau de dimensions MxNxPxQ, un vecteur de dimension T peut être mis en correspondance comme suit:

           MxNxPxQ

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

Dans chaque cas, T doit être égal à la dimension correspondante du tableau de rang supérieur. Les valeurs du vecteur sont ensuite diffusées de la dimension correspondante vers toutes les autres dimensions.

Pour faire correspondre une matrice TxV sur le tableau MxNxPxQ, une paire de dimensions de diffusion est utilisée:

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

L'ordre des dimensions dans le tuple de diffusion doit être l'ordre dans lequel les dimensions du tableau de rang inférieur doivent correspondre aux dimensions du tableau de rang supérieur. Le premier élément du tuple indique quelle dimension du tableau de rang supérieur doit correspondre à la dimension 0 dans le tableau de rang inférieur. Le deuxième élément pour la dimension 1, et ainsi de suite. L'ordre des dimensions de diffusion doit être strictement croissant. Par exemple, dans l'exemple précédent, il est illégal de faire correspondre V à N et T à P; il est également illégal de faire correspondre V à P et N.

Diffusion de tableaux de rang similaire avec des dimensions dégénérées

Un problème de diffusion connexe est la diffusion de deux tableaux qui ont le même rang mais des tailles de dimension différentes. De la même manière que les règles de Numpy, cela n'est possible que lorsque les tableaux sont compatibles . Deux tableaux sont compatibles lorsque toutes leurs dimensions sont compatibles. Deux dimensions sont compatibles si:

  • Ils sont égaux, ou
  • L'un d'eux est 1 (une dimension «dégénérée»)

Lorsque deux tableaux compatibles sont rencontrés, la forme de résultat a le maximum parmi les deux entrées à chaque index de dimension.

Exemples:

  1. (2,1) et (2,3) diffusés sur (2,3).
  2. (1,2,5) et (7,2,5) diffusé vers (7,2,5)
  3. (7,2,5) et (7,1,5) diffusé vers (7,2,5)
  4. (7,2,5) et (7,2,6) sont incompatibles et ne peuvent pas être diffusés.

Un cas particulier se présente, et est également pris en charge, où chacun des tableaux d'entrée a une dimension dégénérée à un index différent. Dans ce cas, le résultat est une "opération externe": (2,1) et (1,3) diffusées vers (2,3). Pour plus d'exemples, consultez la documentation Numpy sur la diffusion .

Composition de diffusion

La diffusion d'une matrice de rang inférieur vers une matrice de rang supérieur et la diffusion utilisant des dimensions dégénérées peuvent toutes deux être effectuées dans la même opération binaire. Par exemple, un vecteur de taille 4 et une matrice de taille 1x2 peuvent être additionnés en utilisant la valeur des dimensions de diffusion de (0):

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

Tout d'abord, le vecteur est diffusé jusqu'au rang 2 (matrice) en utilisant les dimensions de diffusion. La valeur unique (0) dans les dimensions de diffusion indique que la dimension zéro du vecteur correspond à la dimension zéro de la matrice. Cela produit une matrice de taille 4xM où la valeur M est choisie pour correspondre à la taille de dimension correspondante dans le tableau 1x2. Par conséquent, une matrice 4x2 est produite:

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

Ensuite, "diffusion de dimension dégénérée" diffuse la dimension zéro de la matrice 1x2 pour correspondre à la taille de dimension correspondante du côté droit:

 |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 exemple plus compliqué est une matrice de taille 1x2 ajoutée à un tableau de taille 4x3x1 en utilisant des dimensions de diffusion de (1, 2). Tout d'abord, la matrice 1x2 est diffusée jusqu'au rang 3 en utilisant les dimensions de diffusion pour produire un tableau intermédiaire Mx1x2 où la taille de dimension M est déterminée par la taille de l'opérande plus grand (le tableau 4x3x1) produisant un tableau intermédiaire 4x1x2. Le M est à la dimension 0 (dimension la plus à gauche) car les dimensions 1 et 2 sont mappées aux dimensions de la matrice 1x2 d'origine comme la dimension de diffusion le sont (1, 2). Ce tableau intermédiaire peut être ajouté à la matrice 4x3x1 en utilisant la diffusion de dimensions dégénérées pour produire un résultat de tableau 4x3x2.