形状和布局 
XLA 的 Shape 协议(proto) (xla_data.proto) 描述了一个 N 维数组(简称数组)的秩、尺寸和数据类型。
术语、符号和约定 
- 数组的秩等于维数。数组的真秩是大小大于 1 的维数。 
- 对于一个 - N维数组,维度的取值为- 0到- N-1。维数只不过是出于方便性而给出的一些比较任意的标签。它们的顺序并没有反映数组内存布局的主从次序。内存布局是由- Layout协议确定的。
- 按照约定,维度列表是按照维数升序排列的。比如,一个三维数组的尺寸为 - [A x B x C],0 维大小为- A,1 维大小为- B,而 2 维大小为- C。
XLA 中有些工具也支持负值索引,这和 Python 类似;维度 -1 指的是最后一个维度(对于 N 维数组,-1 等价于 N-1)。比如,对于前面描述的三维数组,-1 维的大小为 C,-2 维大小为 B,以此类推。
- 二维、三维和四维数组通常用特定的字母来表示每个维度。比如,对于二维数组: - 0 维: y
- 1 维: x
 
- 0 维: 
对于三维数组:
*   0 维: `z`
*   1 维: `y`
*   2 维: `x`
对于四维数组:
*   0 维: `p`
*   1 维: `z`
*   2 维: `y`
*   3 维: `x`
- XLA API 中的函数接收的维度参数是按照升序排列的,这与 - initializer_list传入的维度顺序是一致的,比如:- ShapeUtil::MakeShape(F32, {A, B, C, D})- 将生成一个形状,它的维度尺寸列表为如下序列: - [A, B, C, D].
布局 
Layout(布局)协议描述了如何在内存中表示一个数组。这个 Layout 协议包含如下字段:
message Layout {
  repeated int64 minor_to_major = 1;
  repeated int64 padded_dimensions = 2;
  optional PaddingValue padding_value = 3;
}维度的主次排序 
minor_to_major 是唯一的必填字段。它描述了形状内维度的主次排序。minor_to_major 中的值是数组(对于 N 维数组,取值为 0 到 N-1)维度的排序,第一个值是维度中最次要的维度,依次排列,最后一个值为最主要的维度。最次要的维度指的是在数组的线性内存中移动时变化最快的那个维度。
比如,考虑如下二维数组,其尺寸为 [2 x 3]:
a b c
d e f这里的 0 维大小为 2,1 维大小为 3。如果布局的 minor_to_major 域为 [0, 1], 则 0 维为最次要维度,1 维为最主要维度,对应于如下线性内存布局:
a d b e c f这里的维度主次顺序类似于二维矩阵的列主序。假设维度主次顺序是单调的,这种布局的另一种叫法是“0 维是最次序”。
相反,如果布局中的 minor_to_major 域为 [1, 0],则线性内存布局为:
a b c d e f对于 N 维数组,N-1 依次减小为 0 的主次排序类似域二维矩阵的行主序。假设维度的主次顺序是单调的,这种布局的另一种叫法是“0 维是最主序”。
默认主次排序 
新创建的形状的默认主次排序是“维度顺序是主到次”,类似于二维矩阵的行主序。
填充 
填充是在可选的 padded_dimensions 和 padding_value 字段中定义的。字段 padded_dimensions 描述了每个维度边缘填充的大小(宽度)。如果指定了这个字段,padded_dimensions 中的元素个数必须等于形状的秩。
以前面定义的 [2 x 3] 数组为例,如果 padded_dimension 为 [3, 5],则 0 维边缘填充的宽度为 3,而 1 维是 5 。其线性内存布局为(假设填充值为 0,且为列主序):
a d 0 b e 0 c f 0 0 0 0 0 0 0这等价于采用相同主次排序的下列数组的内存布局:
a b c 0 0
d e f 0 0
0 0 0 0 0数组的索引 
IndexUtil 类定义在 index_util.h 文件中,它提供了一些在给定形状和布局的情况下多维索引和线性索引之间的转换工具。多维索引为每个维度指定了一个 int64 索引。线性索引只不过是单个 int64 的值,它是数组线性缓存的索引。想要了解更多关于简化形状和布局的创建和操作的工具,参见 shape_util.h 和 layout_util.h 这两个文件,它们在同一个源码目录下。
