Formes et mise en page

Le proto Shape XLA (xla_data.proto) décrit le rang, la taille et le type de données d'un tableau à N dimensions (tableau en abrégé).

Terminologie, notation et conventions

  • Le rang d'un tableau est égal au nombre de dimensions. Le classement réel d'un tableau correspond au nombre de dimensions de taille supérieure à 1.

  • Pour un tableau de dimensions N, les dimensions sont numérotées de 0 à N-1. Pour plus de commodité, les numéros de dimension sont des libellés arbitraires. L'ordre de ces numéros de dimension n'implique pas d'ordre mineur/majeur particulier dans la mise en page de la forme. La mise en page est déterminée par le proto Layout.

  • Par convention, les dimensions sont répertoriées par ordre croissant de numéro de dimension. Par exemple, pour un tableau tridimensionnel de taille [A x B x C], la dimension 0 a la taille A, la dimension 1 a la taille B et la dimension 2 la taille C.

    Certains utilitaires de XLA sont également compatibles avec l'indexation négative de type Python : "Dimension -1" correspond à la dernière dimension (équivalent à N-1 pour un tableau de dimensions N). Par exemple, pour le tableau tridimensionnel décrit ci-dessus, la dimension -1 a la taille C, la dimension -2 a la taille B, etc.

  • Les tableaux à deux, trois et quatre dimensions comportent souvent des lettres spécifiques associées à des dimensions. Par exemple, pour un tableau bidimensionnel:

    • dimension 0: y
    • dimension 1: x

    Pour un tableau 3D:

    • dimension 0: z
    • dimension 1: y
    • dimension 2: x

    Pour un tableau 4D:

    • dimension 0: p
    • dimension 1: z
    • dimension 2: y
    • dimension 3: x
  • Les fonctions de l'API XLA qui prennent des dimensions le font par ordre croissant du nombre de dimension. Cet ordre correspond à l'ordre utilisé lors de la transmission des dimensions sous forme de initializer_list. Par exemple,

    ShapeUtil::MakeShape(F32, {A, B, C, D})

    crée une forme dont le tableau de dimensions est constitué de la séquence [A, B, C, D].

Mise en page

Le fichier proto Layout décrit comment un tableau est représenté en mémoire. Le fichier proto Layout comprend les champs suivants:

message Layout {
  repeated int64 minor_to_major = 1;
  repeated int64 padded_dimensions = 2;
  optional PaddingValue padding_value = 3;
}

Ordre des dimensions mineures à majeures

Le seul champ obligatoire est minor_to_major. Ce champ décrit l'ordre de grande valeur des dimensions dans une forme. Les valeurs dans minor_to_major correspondent à l'ordre des dimensions du tableau (0 à N-1 pour un tableau de dimensions N), la première valeur étant la dimension la plus mineure jusqu'à la dernière valeur, qui est la dimension la plus grande. La dimension la plus mineure est celle qui change le plus rapidement lors de la navigation dans les éléments du tableau disposés en mémoire linéaire.

Prenons l'exemple du tableau 2D suivant, de taille [2 x 3]:

a b c
d e f

Ici, la dimension 0 correspond à la taille 2, et la dimension 1 à la taille 3. Si le champ minor_to_major de la mise en page est [0, 1], la dimension 0 est la dimension la plus mineure et la dimension 1 est la dimension la plus importante. Cela correspond à la mise en page suivante en mémoire linéaire:

a d b e c f

Cet ordre des dimensions mineures à majeures (0 jusqu'à N-1) s'apparente à colonne-majeure (au rang 2). En supposant un ordre monotone des dimensions, une autre façon dont nous pouvons faire référence à cette mise en page dans le code est simplement "dim 0 is minor".

En revanche, si le champ minor_to_major de la mise en page est [1, 0], la mise en page en mémoire linéaire se présente comme suit:

a b c d e f

Un ordre de dimension mineur à majeure de N-1 à 0 pour un tableau de dimensions N s'apparente à row-major (au rang 2). En supposant un ordre monotone des dimensions, une autre façon de désigner cette mise en page dans le code est simplement "dim 0 is major".

Ordre de priorité mineur à majeur par défaut

La mise en page par défaut pour les formes nouvellement créées est "l'ordre des dimensions est majeur à mineur" (similaire à la ligne-majeure au rang 2).

Marge intérieure

La marge intérieure est définie dans les champs facultatifs padded_dimensions et padding_value. Le champ padded_dimensions décrit les tailles (largeurs) auxquelles chaque dimension est remplie. Le cas échéant, le nombre d'éléments dans padded_dimensions doit être égal au rang de la forme.

Par exemple, pour le tableau [2 x 3] défini ci-dessus, si padded_dimensions est [3, 5], la dimension 0 est complétée jusqu'à une largeur de 3, et la dimension 1 est complétée jusqu'à une largeur de 5. La mise en page en mémoire linéaire (en supposant une valeur de marge intérieure de 0 et une mise en page de type colonne majeure) est la suivante:

a d 0 b e 0 c f 0 0 0 0 0 0 0

Cela équivaut à la mise en page du tableau suivant avec le même ordre des dimensions mineures à majeures:

a b c 0 0
d e f 0 0
0 0 0 0 0

Indexation dans des tableaux

La classe IndexUtil dans index_util.h fournit des utilitaires permettant de convertir des index multidimensionnels et des indices linéaires en fonction d'une forme et d'une mise en page. Les index multidimensionnels incluent un indice int64 pour chaque dimension. Les index linéaires sont une valeur int64 unique qui s'indexe dans le tampon contenant le tableau. Consultez shape_util.h et layout_util.h dans le même répertoire pour découvrir les utilitaires qui simplifient la création et la manipulation de formes et de mises en page.