Ascend C关键分形格式详解

Ascend C关键分形格式详解
关键分形格式详解【免费下载链接】asc-devkit本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言原生支持C和C标准规范主要由类库和语言扩展层构成提供多层级API满足多维场景算子开发诉求。项目地址: https://gitcode.com/cann/asc-devkit矩阵分形存储格式是对多维Tensor在内存中数据排布格式的描述。为了适配矩阵计算单元的物理读取路径不同的产品形态有不同的格式要求Zz × Zn NzA × B C组合矩阵乘法A × B C要求左矩阵A使用Zz格式右矩阵B使用Zn格式结果矩阵C使用Nz格式如图1所示。这种分形格式组合适用于Atlas A2训练系列产品/Atlas A2推理系列产品Atlas A3训练系列产品/Atlas A3推理系列产品Atlas 200I/500 A2 推理产品Atlas 推理系列产品Atlas 训练系列产品Kirin X90Kirin 9030图1矩阵乘法场景涉及的数据格式![](https://raw.gitcode.com/cann/asc-devkit/raw/1cd1d1192e01ae4a8684cd07552c35e13e5c4bdf/docs/zh/api/figures/fractals_involved_in_matrix_calculation_a2a3.png 矩阵乘法场景涉及的数据格式?utm_sourcegitcode_repo_files)Nz × Zn NzA × B C组合针对Ascend 950PR/Ascend 950DT矩阵乘法C A×B要求左矩阵A使用Nz格式右矩阵B使用Zn格式结果矩阵C使用Nz格式如图2所示图2矩阵乘法场景涉及的数据格式![](https://raw.gitcode.com/cann/asc-devkit/raw/1cd1d1192e01ae4a8684cd07552c35e13e5c4bdf/docs/zh/api/figures/fractals_involved_in_matrix_calculation_950.png 矩阵乘法场景涉及的数据格式-27?utm_sourcegitcode_repo_files)在具体的矩阵乘法场景中各格式的详细定义与物理成因如下ND格式N-Dimension定义通用的N维张量格式即“线性格式”数据在内存中是连续线性的。场景通常存在于Global MemoryGM中。在进行矩阵运算前通常需要将其转换为Nz格式以适配Cube单元。转换示例从NDGM到NzL1 Buffer的数据格式转换见图3图中展示了一个具体的M40K56的矩阵数据类型为half在从Global MemoryGM搬运至L1 Buffer并转换为Nz格式时的内存排布变化原始数据ND格式左侧GM中存储的是原始矩阵shape为40 x 56。数据呈线性连续排布图中长箭头所示遵循row major行主序规则。对齐与填充Padding由于Cube单元的分形Fractal要求目标矩阵必须能够被16 x 16的Block整除假设数据类型为half即32/sizeof(half)16。M轴填充原始M40不能被16整除需向上补齐至4816 x 3。K轴填充原始K56不能被16整除需向上补齐至6416 x 4。图中灰色区域即为补齐产生的无效数据Padding白色区域为原始有效数据。重排布Nz格式右侧L1 Buffer中数据被重组为3 x 4个分形块。Z字流动每个16 x 16的小方块内部以及方块之间均按照特定的Z字形顺序存储如图中折线箭头所示完成了从“线性”到“分形”的物理映射做好了进入Cube计算的准备。图3NDGM到NzL1 Buffer的数据转换DN格式Dimension-N定义通用的N维张量格式其物理存储顺序对应于ND格式在内存维度上的转置排列即ND遵循row major行主序规则DN遵循column major列主序。列主序示意图如下所示场景通常存在于Global MemoryGM中。若此输入要作为矩阵计算的输入需要转换成Nz格式。转换示例针对Ascend 950PR/Ascend 950DT可以使用矩阵搬入DataCopy DN2NZ接口将其转换为Nz格式以适配Cube单元。Zz格式FRACTAL_Zz定义大Z外部row major行主序 小z内部row major行主序见图4。图4Zz格式以half类型为例物理位置通常位于L0A Buffer作为左矩阵。设计原理行读取需求在A×B中A矩阵是被“横向扫描”的。内存一致性Zz格式在微观上按行存储这意味着A矩阵同一行的相邻元素在L0A Buffer的物理地址是连续的。Cube单元左侧通道可直接通过DMA连续读取无需跨步Stride。格式转换过程对一个Tensor的最低两维进行填充pad、拆分reshape和转置transpose。具体转换过程如下M, K大小的矩阵被分为M1 * K1个分形按照row major行主序排布形状如Z字形每个分形内部有M0 * K0个元素按照row major行主序排布形状如Z字形所以这种数据格式称为Zz格式。其中M0, K0表示一个分形的大小分形Shape为16 x (32B / sizeof(Datatype))大小为512字节。通过公式表达转换过程如下(…, B, M, K)-pad-(…, B, M1 * M0, K1 * K0)-reshape-(…, B, M1, M0, K1, K0)-transpose-(…, B, M1, K1, M0, K0)分形大小约束其中M016而K0的大小取决于数据类型位宽32-bitfloat/int32K08分形16x816-bithalfK016分形16x168-bitint8K032分形16x324-bitK064分形16x64Zn格式FRACTAL_Zn定义大Z外部row major行主序 小n内部column major列主序见图5。图5Zn格式以half类型为例物理位置L0B Buffer作为右乘矩阵。L1 Buffer / GM数据流转使用一般用于保存离线处理好的右乘矩阵数据。设计原理列读取需求矩阵乘法需要取B矩阵的一列。若B矩阵为普通row major行主序同一列的数据在内存中会相隔整整一行导致地址跳跃。Zn的作用Zn格式在分形内部强制按列存储。这意味着B矩阵中逻辑上的一列数据在L0B Buffer物理内存中被强行排在了一起Cube单元只需线性读取即可天然获得B矩阵的列向量。格式转换过程K, N大小的矩阵被分为K1 * N1个分形按照row major行主序排布形状如Z字形每个分形内部有K0 * N0个元素按照column major列主序排布形状如N字形所以这种数据格式称为Zn格式。其中N0K0表示一个分形的大小分形shape为 16 x (32B / sizeof(Datatype))大小为512字节。通过公式表达转换过程如下(…, B, K, N)-pad-(…, B, K1 * K0, N1 * N0)-reshape-(…, B, K1, K0, N1, N0)-transpose-(…, B, K1, N1, N0, K0)分形大小约束其中N016而K0的大小同样取决于数据类型规则同Zz格式例如half类型下分形为16x16int8下分形为16x32。Nz格式FRACTAL_Nz定义大N外部column major列主序 小z内部row major行主序见图6。图6Nz格式![](https://raw.gitcode.com/cann/asc-devkit/raw/1cd1d1192e01ae4a8684cd07552c35e13e5c4bdf/docs/zh/api/figures/nz_fractals_of_half_for_cmatrix.png Nz-格式?utm_sourcegitcode_repo_files)物理位置L0C Buffer存储矩阵乘法的结果分形固定为16x16。L1 Buffer / GM数据流转的通用中间格式分形为16xK0K0的大小取决于数据类型位宽。L0A Buffer仅Ascend 950PR/Ascend 950DT下使用用于存储左矩阵分形为16xK0K0的大小取决于数据类型位宽。设计原理Nz是昇腾芯片架构内部的“中间标准格式”。它是对“线性数据ND”和“计算专用数据Zz/Zn”的一种折中。大N排布column major列主序Block的设计通常是为了配合多核并行或后续算子如Vector向量计算在处理通道Channel维度数据时的便利性。说明通常情况下Nz格式在L0C Buffer和L1 Buffer中分别用于不同的场景在L0C Buffer中Nz格式用于存储矩阵乘法的结果。其分形形状为16x16包含256个元素这种结构非常适合Cube计算单元进行高效的矩阵乘法运算。在L1 Buffer中Nz格式被采用以便于将数据搬运到L0A Buffer和L0B Buffer时能够方便地转换为对应的Zz和Zn格式。此时分形形状为16 x (32B / sizeof(Datatype))大小为512字节。 因此当数据从L0C Buffer搬运到L1 Buffer时其分形大小可能会发生变化。针对Ascend 950PR/Ascend 950DTNz格式在L0A Buffer中用于存储左矩阵。Nz格式转换详解与示例由于Nz格式是最常见的数据格式我们以ND转Nz为例详细说明数据格式转换过程。转换过程MN大小的矩阵被分为M1 * N1个分形按照column major列主序排布形状如N字形每个分形内部有M0 * N0个元素按照row major行主序排布形状如Z字形所以这种数据格式称为Nz格式。其中M0, N0表示一个分形的大小。转换公式(…, B, M, N)-pad-(…, B, M1 * M0, N1 * N0)-reshape-(…, B, M1, M0, N1, N0)-transpose-(…, B, N1, M1, M0, N0)转换示例下面通过一个具体的例子来了解ND格式转换为Nz格式的过程。原始Tensor的Shape为20, 28data [x for x in range(20 * 28)] data_a data * np.ones((20 * 28), dtypefloat16) tensor_a data_a.reshape((20, 28)) print(tensor_a)原始Tensor数据打印如下[[ 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27.] ... [532. 533. 534. 535. 536. 537. 538. 539. 540. 541. 542. 543. 544. 545. 546. 547. 548. 549. 550. 551. 552. 553. 554. 555. 556. 557. 558. 559.]]转换过程通过伪代码表达如下N0 16 N1 (28 N0 - 1) // N0 pad_n N1 * N0 - 28 M0 16 M1 (20 M0 - 1) // M0 pad_m M1 * M0 - 20 tensor_b np.pad(tensor_a, [[0, pad_m], [0, pad_n]]) tensor_b tensor_b.reshape((M1, M0, N1, N0)) tensor_b tensor_b.transpose((2, 0, 1, 3)) print(tensor_b)转换过程示意图如下转换后Tensor打印如下 py [[[[ 0. 1. 2. ... 13. 14. 15.] [ 28. 29. 30. ... 41. 42. 43.] [ 56. 57. 58. ... 69. 70. 71.] ... [ 0. 0. 0. ... 0. 0. 0.] [ 0. 0. 0. ... 0. 0. 0.] [ 0. 0. 0. ... 0. 0. 0.]]] [[[ 16. 17. 18. ... 0. 0. 0.] [ 44. 45. 46. ... 0. 0. 0.] [ 72. 73. 74. ... 0. 0. 0.] ... [ 0. 0. 0. ... 0. 0. 0.] [ 0. 0. 0. ... 0. 0. 0.] [ 0. 0. 0. ... 0. 0. 0.]]]] NC1HWC0格式定义NC1HWC0是一种用于卷积加速的数据格式。通过将NHWC数据在C维度进行split变成C1份NHWC0然后将C1份NHWC0在内存中连续排列变成NC1HWC0。C0固定为32ByteC1C/C0如果结果不整除最后一份数据需要padding到C0。图7NHWC-NC1HWC0![](https://raw.gitcode.com/cann/asc-devkit/raw/1cd1d1192e01ae4a8684cd07552c35e13e5c4bdf/docs/zh/api/figures/nhwc2nc1hwc0.png NHWC--NC1HWC0?utm_sourcegitcode_repo_files)物理位置通常位于Global MemoryGM或者L1 Buffer中作为卷积的Feature Map输入。格式转换过程通常使用随路转换-ND2NZ搬运DataCopy指令来进行NHWC格式到NC1HWC0格式的转换。通过二维数据排布变换表达格式转换过程【免费下载链接】asc-devkit本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言原生支持C和C标准规范主要由类库和语言扩展层构成提供多层级API满足多维场景算子开发诉求。项目地址: https://gitcode.com/cann/asc-devkit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考