Files
wehub-resource-sync 8a852e4b4e
cffconvert / validate (push) Has been skipped
License Check / license-check (push) Failing after 2s
chore: import upstream snapshot with attribution
2026-07-13 12:14:16 +08:00

205 lines
7.4 KiB
Markdown

# Shapes and layout
## Structure of an XLA Op
Consider an example HLO:
```
add.936 = bf16[8,1,1280,16384]{3,2,0,1:T(8,128)(2,1)}
add(exponential.183, broadcast.3115)
```
This consists of the following components:
* Op Name: `add.936`
* This is the unique name for the operation.
* Shape: `bf16[8,1,1280,16384]`
* This is the output shape of the Op. Here the dtype is
[bf16](https://en.wikipedia.org/wiki/Bfloat16_floating-point_format) and
the shape is `[8,1,1280,16384]`.
* Layout (with Tiling): `3,2,0,1:T(8,128)(2,1)`
* This describes how the array is stored in memory. `3,2,0,1` denotes the
order of the axes in memory (i.e., column major, row major, etc.) and
`T(8,128)(2,1)` denotes the tiling & padding used.
* Layout is optional. If not specified, there is no tiling and the
dimensions are assumed to be ordered from most-major to most-minor.
* Operation: `add`
* The operation being performed. Here, it is
[Add](operation_semantics.md#add), which is also mentioned in the Op
name.
* Arguments: `exponential.183`, `broadcast.3115`
* This operation takes two arguments, specified with their unique names.
Let's consider another example, a fusion Op:
```
%fusion.3 = bf16[32,32,4096]{2,1,0:T(8,128)(2,1)S(1)}
fusion(bf16[32,32,8192]{2,1,0:T(8,128)(2,1)S(1)} %fusion.32),
kind=kCustom, calls=%all-reduce-scatter.3
```
In addition to the previously described components, this consists of:
* Attributes: `kind` and `calls`
* These provide more information about the operation being performed, in
this case: fusion.
* Memory location (memory space identifier): `S(1)`
* This denotes the memory space/location where the array is stored. `S(1)`
here denotes this array lives in VMEM (on a TPU).
* Shape and layout details for the input argument `%fusion.32`
The following sections describe Shapes, [Layout](#layout), and
[Memory Space Identifiers](#memory-space-identifiers). You can learn more about
Tiling in [Tiled Layout](tiled_layout.md).
## Shapes
The XLA `ShapeProto` proto
([xla_data.proto](https://github.com/openxla/xla/tree/main/xla/xla_data.proto))
describes the number of dimensions, size, and data type of an N-dimensional
array (*array* in short).
### Terminology, notation, and conventions
NOTE: in the past, XLA has used the term "rank" to mean the number of dimensions
of an array. We have stopped this usage as it's inconsistent with the matrix
rank concept in linear algebra. However, you may still see the name `rank` used
in legacy documentation and some of the code.
* The *true number of dimensions* of an array is the number of dimensions
which have a size greater than 1.
* Dimensions are numbered from `0` up to `N-1` for an `N` dimensional array.
The size of a dimension is a non-negative integer. In particular, size 0 is
valid. The dimension numbers are arbitrary labels for convenience. The
order of these dimension numbers does not imply a particular minor/major
ordering in the layout of the shape. The layout is determined by the
`LayoutProto` proto.
* By convention, dimensions are listed in increasing order of dimension
number. For example, for a 3-dimensional array of size `[A x B x C]`,
dimension 0 has size `A`, dimension 1 has size `B`, and dimension 2 has size
`C`.
Some utilities in XLA also support Python-like negative indexing: Dimension
-1 is the last dimension (equivalent to `N-1` for an `N` dimensional array).
For example, for the 3-dimensional array described above, dimension -1 has
size `C`, dimension -2 has size `B`, and so on.
* Two, three, and four dimensional arrays often have specific letters
associated with dimensions. For example, for a 2D array:
* dimension 0: `y`
* dimension 1: `x`
For a 3D array:
* dimension 0: `z`
* dimension 1: `y`
* dimension 2: `x`
For a 4D array:
* dimension 0: `p`
* dimension 1: `z`
* dimension 2: `y`
* dimension 3: `x`
* Functions in the XLA API which take dimensions do so in increasing order of
dimension number. This matches the ordering used when passing dimensions as
an `initializer_list`; e.g.
`ShapeUtil::MakeShape(F32, {A, B, C, D})`
will create a shape whose dimension size array consists of the sequence `[A,
B, C, D]`.
## Layout
The `LayoutProto` proto describes how an array is represented in memory. It
includes the following fields:
```
message LayoutProto {
repeated int64 minor_to_major;
int64 tail_padding_alignment_in_elements;
...
}
```
### Minor-to-major dimension ordering
The only required field is `minor_to_major`. This field describes the
minor-to-major ordering of the dimensions within a shape. Values in
`minor_to_major` are an ordering of the dimensions of the array (`0` to `N-1`
for an `N` dimensional array) with the first value being the most-minor
dimension up to the last value which is the most-major dimension. The most-minor
dimension is the dimension which changes most rapidly when stepping through the
elements of the array laid out in linear memory.
For example, consider the following 2D array of size `[2 x 3]`:
```
a b c
d e f
```
Here dimension `0` is size 2, and dimension `1` is size 3. If the
`minor_to_major` field in the layout is `[0, 1]` then dimension `0` is the
most-minor dimension and dimension `1` is the most-major dimension. This
corresponds to the following layout in linear memory:
```
a d b e c f
```
This minor-to-major dimension order of `0` up to `N-1` is akin to *column-major*
(for 2-dimensionals). Assuming a monotonic ordering of dimensions, another way
we may refer to this layout in the code is simply "dim 0 is minor".
On the other hand, if the `minor_to_major` field in the layout is `[1, 0]` then
the layout in linear memory is:
```
a b c d e f
```
A minor-to-major dimension order of `N-1` down to `0` for an `N` dimensional
array is akin to *row-major* (for 2-dimensionals). Assuming a monotonic
ordering of dimensions, another way we may refer to this layout in the code is
simply "dim 0 is major".
#### Default minor-to-major ordering
The default layout for newly created Shapes is "dimension order is
major-to-minor" (i.e. `[N-1, ..., 0]`).
### Padding
The `tail_padding_alignment_in_elements` field defines the alignment of the
[tiled](tiled_layout.md) array in terms of the number of elements. After
applying tiling, padded elements will be added at the end of the layout until
the total number of elements is a multiple of this value.
### Indexing into arrays
The class `IndexUtil` in
[index_util.h](https://github.com/openxla/xla/tree/main/xla/index_util.h)
provides utilities for converting between multidimensional indices and linear
indices given a shape and layout. Multidimensional indices include an `int64`
index for each dimension. Linear indices are a single `int64` value which
indexes into the buffer holding the array. See `shape_util.h` and
`layout_util.h` in the same directory for utilities that simplify creation and
manipulation of shapes and layouts.
## Memory Space Identifiers
In HLO, each array may be annotated with a memory space identifier, written as
S(n).
* `S(0)` (often omitted) denotes device high bandwidth memory (HBM).
* `S(1)` represents on device virtual memory (VMEM).
* `S(2)`, `S(3)`, etc., correspond to additional device specific memory
spaces.
* `S(5)` indicates host memory.