已关闭
feat(pypto_pro):Provide R3 design document #588
xuxinlei321创建于 24 天前关闭于 7 天前
feat(pypto_pro):Provide R3 design document #588
已关闭
共 2 个文件变更+203-25
| @@ -121,34 +121,17 @@ EXPLORE_REPORT.md §3只用于提供候选映射。逐项核对API参考页后 | |||
| 121 | 121 | ||
| 122 | **核心问题**:每块 tile 放在哪个内存空间的哪个地址?如何分配管理? | 122 | **核心问题**:每块 tile 放在哪个内存空间的哪个地址?如何分配管理? |
| 123 | 123 | ||
| 124 | -**内存空间**:tile 按 R2 确定的 `target_memory` 落到不同片上空间,**每个空间独立寻址、独立限容**——地址各自从 `0x00000` 起算,同一 addr 值在不同空间是不同物理位置。 | 124 | +> 📌 **权威依据(必读)**:读取[片上空间布局](references/onchip_memory_layout.md)。按其流程展开全部物理槽位,逐空间检查地址区间、对齐、容量和地址复用证明;当前平台容量仍以`EXPLORE_REPORT.md` §7为准。 |
| 125 | 125 | ||
| 126 | -- `Vec`(UB):vector 计算用;纯 vector 算子只涉及此空间(`TileType.md` 参数范围表:`Vec` 对应 UB) | 126 | +**执行要点**: |
| 127 | -- `Mat`(L1)、`Left`(L0A)、`Right`(L0B)、`Acc`(L0C):含 cube/matmul 的算子涉及。`matmul` 的操作数内存空间是**硬性约束**——`lhs` 只能 `Left`(L0A)、`rhs` 只能 `Right`(L0B)、`dst` 只能 `Acc`(L0C),放错空间即报错 | ||
| 128 | -- 典型数据流:`GM --load--> L1(Mat) --move--> L0A/L0B --matmul--> L0C(Acc)`,结果既可从 Acc 直接 `store` 回 GM,也可先 `move` 到 UB 再后处理/store | ||
| 129 | 127 | ||
| 130 | -**流程**: | 128 | +1. 按`target_memory`分组,依据当前前端规则计算每个物理槽位的字节数和左闭右开地址区间。 |
| 129 | +2. 展开TileGroup的所有槽位,逐槽位检查首地址对齐;单基地址和离散地址列表的语义以`make_tile_group.md`和当前实现为准。 | ||
| 130 | +3. 同一空间内的并存区间不得重叠;逻辑Tile复用物理区间时,记录生命周期和同步证明。 | ||
| 131 | +4. 容量按MemorySpace独立校验,使用当次`EXPLORE_REPORT.md` §7的探测值和该空间的最高地址上界;地址空洞也计入上界。 | ||
| 132 | +5. MX路径额外检查`ScaleLeft`/`ScaleRight`与配对`Left`/`Right`的地址映射;计划并行访问的Mat Tile额外做L1 Bank冲突检查。 | ||
| 131 | 133 | ||
| 132 | -1. 按 `target_memory` 把 R2 的 tile 分组,**每个内存空间各自从 `0x00000` 开始**连续排列地址,不重叠。UB/L1 首地址须 32 字节对齐;L0A/L0B/L0C 的对齐以对应 API 文档 / 官方指定算子为准。 | 134 | +**输出**:DESIGN.md §3。按[片上空间布局](references/onchip_memory_layout.md)给出逐物理槽位的地址表、逐空间容量计算,以及所有地址复用的证明表。若超限,带着空间名、最高地址上界、容量和字节差额回退R2,必要时再回退R1。 |
| 133 | -2. 标注同地址不同 layout 的 tile 对(如有) | ||
| 134 | -3. 分配方式应使用 `make_tile_group` + `auto_mutex`,由框架自动管理 buffer 切换与同步(见上方「实现约束」)。 | ||
| 135 | -4. **逐空间**验证该空间上的 tile 总大小不超过其容量上限。容量值以 EXPLORE_REPORT §7 探测记录为准——§7 必含 UB 容量;含 cube 时须补探 L1/L0 各空间容量(§7 未记录则回退 material-explore 补测,不得在此臆测数值) | ||
| 136 | -5. **double buffer 地址规划**:`make_tile_group` 的 buffer 数 > 1 时地址占用按倍数放大,须在地址表中显式反映(buffer 数、受影响 tile、是否需 PONG 地址)。buffer 数取值参照官方指定算子中相似算子的实际配置 | ||
| 137 | - | ||
| 138 | -**输出**:片上地址映射表(**按内存空间分节**,纯 vector 算子只有 UB 一节): | ||
| 139 | - | ||
| 140 | -| 内存空间 | 用途 | 变量名 | shape | dtype | layout | 地址 | 大小 | 备注 | | ||
| 141 | -|---------|------|--------|-------|-------|--------|------|------|------| | ||
| 142 | -| UB(Vec) | 输入暂存 | `tile_a` | `[64,128]` | FP32 | `—` | `0x00000` | 32768 | ... | | ||
| 143 | -| L1(Mat) | A 矩阵暂存 | `a_l1` | `[128,128]` | FP16 | `—` | `0x00000` | 32768 | ... | | ||
| 144 | -| L0C(Acc) | 累加结果 | `acc` | `[128,128]` | FP32 | `—` | `0x00000` | 65536 | Acc FP32 自动 fractal | | ||
| 145 | -| ... | ... | ... | ... | ... | ... | ... | ... | ... | | ||
| 146 | - | ||
| 147 | -> `—` 表示 layout 列留空即用该内存空间的默认布局(Vec 无约束;其余空间见 `TileType.md` 默认布局表);非默认布局显式写出,具体值以 API 文档为准。 | ||
| 148 | - | ||
| 149 | -**各空间总用量**(逐空间列出,无对应 tile 的空间可省略): | ||
| 150 | -- UB(Vec): {∑ 大小} / {§7 UB 容量} = {百分比} | ||
| 151 | -- L1(Mat) / L0A / L0B / L0C(如有 cube): {∑ 大小} / {§7 对应容量} = {百分比}——各空间容量来自 §7 探测记录 | ||
| 152 | 135 | ||
| 153 | --- | 136 | --- |
| 154 | 137 | ||
| @@ -0,0 +1,195 @@ | |||
| 1 | +# 片上空间布局 | ||
| 2 | + | ||
| 3 | +R3将R2确定的每个Tile落到具体的片上地址,并证明地址对齐、空间容量和地址复用均正确。R3不重新选择Tile shape、dtype、layout或缓冲深度;若无法布局,应带着明确的超限空间和字节差额回退R2,必要时再回退R1更换API链。 | ||
| 4 | + | ||
| 5 | +本文与[API映射与Tile规划](api_mapping_and_tile_planning.md)配套使用。接口的当前行为以`$PYPTO_DEVKIT_DIR/docs/pypto_pro/api/SIMD-API/`中的`make_tile.md`、`make_tile_group.md`、`TileType.md`和`MemorySpace.md`为准;平台容量以`EXPLORE_REPORT.md` §7的当次探测结果为准。 | ||
| 6 | + | ||
| 7 | +## R3的输入与输出 | ||
| 8 | + | ||
| 9 | +R3开始前,R2必须已给出: | ||
| 10 | + | ||
| 11 | +- 全部Tile及其`shape`、`dtype`、`target_memory`、`layout`、`fractal`、`pad`和`compact`; | ||
| 12 | +- 每个Tile使用`make_tile`还是`make_tile_group`; | ||
| 13 | +- TileGroup的`depth`、逐槽位`mutex_ids`和访问方式; | ||
| 14 | +- 各Tile的生命周期,包括首次写入、最后一次读取和是否跨循环保留; | ||
| 15 | +- API要求的额外物理空间,例如分形向上对齐或RowPlusOne的额外行。 | ||
| 16 | + | ||
| 17 | +R3的交付物是DESIGN.md §3中的片上地址表、逐空间容量计算和地址复用依据。表中必须展开TileGroup的所有物理槽位,不能只记基地址。 | ||
| 18 | + | ||
| 19 | +## 1. 按MemorySpace分组 | ||
| 20 | + | ||
| 21 | +`target_memory`决定Tile的物理空间和可用API。不同空间独立寻址:例如Vec的`0x00000`与Mat的`0x00000`不是同一块物理存储。地址重叠和容量必须在每个MemorySpace内分别检查,不能跨空间求和或比较地址。 | ||
| 22 | + | ||
| 23 | +| MemorySpace | 物理位置 | 主要用途 | | ||
| 24 | +|---|---|---| | ||
| 25 | +| `Vec` | UB | Vector Tile的输入、输出和中间量 | | ||
| 26 | +| `Mat` | L1 | GM与L0A/L0B之间的矩阵暂存 | | ||
| 27 | +| `Left` | L0A | Cube左操作数 | | ||
| 28 | +| `Right` | L0B | Cube右操作数 | | ||
| 29 | +| `Acc` | L0C | Cube累加结果 | | ||
| 30 | +| `Scaling` | FBuffer | 部分量化、反量化路径的参数 | | ||
| 31 | +| `ScaleLeft` | L0A的MX scale独立地址域 | `matmul_mx`的A矩阵E8M0 scale | | ||
| 32 | +| `ScaleRight` | L0B的MX scale独立地址域 | `matmul_mx`的B矩阵E8M0 scale | | ||
| 33 | + | ||
| 34 | +`Bias`当前没有CCE Tile codegen映射,不能规划为`make_tile`或`make_tile_group`的片上Tile。`Scaling`与`ScaleLeft`/`ScaleRight`是不同空间,不能混用。 | ||
| 35 | + | ||
| 36 | +Cube矩阵乘的常见数据路径为: | ||
| 37 | + | ||
| 38 | +```text | ||
| 39 | +GM --load--> Mat(L1) --move--> Left(L0A) / Right(L0B) | ||
| 40 | +Left × Right --matmul/matmul_acc--> Acc(L0C) | ||
| 41 | +Acc --store--> GM,或 Acc --move--> Vec(UB) --Vector后处理 | ||
| 42 | +``` | ||
| 43 | + | ||
| 44 | +这个路径只用于检查是否漏掉Tile,不代替`load`、`move`、`matmul`和`store`的单接口约束。 | ||
| 45 | + | ||
| 46 | +## 2. 计算每个物理槽位的地址区间 | ||
| 47 | + | ||
| 48 | +地址表统一使用左闭右开区间`[addr, addr + size)`。因此,前一区间的结束地址等于后一区间的起始地址时不构成重叠。 | ||
| 49 | + | ||
| 50 | +### `make_tile_group` | ||
| 51 | + | ||
| 52 | +当`addrs`是单个基地址时,当前前端将第`i`个槽位展开为: | ||
| 53 | + | ||
| 54 | +```text | ||
| 55 | +slot_size = prod(static_shape) × max(1, ceil(dtype_bits / 8)) | ||
| 56 | +slot[i].addr = base + i × slot_size | ||
| 57 | +slot[i].range = [slot[i].addr, slot[i].addr + slot_size) | ||
| 58 | +``` | ||
| 59 | + | ||
| 60 | +shape的每一维必须是正的编译期整数。对INT4等亚字节dtype,当前实现按每元素至少1字节预留,不能直接用`dtype_bits / 8`得到半字节步长。 | ||
| 61 | + | ||
| 62 | +当`addrs`是地址列表时,列表长度必须等于`depth`,每个元素分别指定一个槽位的起始地址。离散地址不会改变`slot_size`。 | ||
| 63 | + | ||
| 64 | +`make_tile_group`当前没有`size`参数,每个槽位的预留大小就是上述`slot_size`。layout、fractal、pad或compact要求更大物理边界时,必须在R2将需求落实到能表示该占用的Tile规格,并用对应API文档或官方样例复核。不能假设TileGroup会因为layout自动扩大槽位。 | ||
| 65 | + | ||
| 66 | +### `make_tile` | ||
| 67 | + | ||
| 68 | +`make_tile`缺省`size`时使用与TileGroup相同的计算公式。仅当单次scratch Tile的实际预留范围大于该缺省值时,才显式填写经API证实的`size`。`size`必须是正的编译期字节数。 | ||
| 69 | + | ||
| 70 | +`valid_shape`只描述当前有效区域,不缩小物理预留范围。容量和地址区间始终按物理shape和实际预留大小计算。 | ||
| 71 | + | ||
| 72 | +## 3. 满足首地址对齐 | ||
| 73 | + | ||
| 74 | +当前`pypto_cann` Pro前端对编译期已知的Tile首地址执行以下对齐检查: | ||
| 75 | + | ||
| 76 | +| MemorySpace | 首地址对齐 | | ||
| 77 | +|---|---:| | ||
| 78 | +| `Vec` | 32B | | ||
| 79 | +| `Mat` | 32B | | ||
| 80 | +| `Left` | 512B | | ||
| 81 | +| `Right` | 512B | | ||
| 82 | +| `Acc` | 64B | | ||
| 83 | +| `ScaleLeft` | 32B | | ||
| 84 | +| `ScaleRight` | 32B | | ||
| 85 | + | ||
| 86 | +`Scaling`当前没有在该前端映射中强制对齐,不等于硬件或具体API没有要求。使用`Scaling`时必须查对应API参考页和官方样例,不在R3自行推断对齐。 | ||
| 87 | + | ||
| 88 | +单个基地址展开TileGroup时,不仅要检查`base`,还要检查每个`base + i × slot_size`是否符合该MemorySpace的对齐。若`slot_size`不是所需对齐的整数倍,应调整R2物理shape或使用显式地址列表,不能只把基地址对齐。 | ||
| 89 | + | ||
| 90 | +## 4. 分配地址与判定复用 | ||
| 91 | + | ||
| 92 | +先为同一MemorySpace内同时存活的物理槽位分配不重叠区间。一个`depth=N`的TileGroup是N个可同时在途的物理Tile,所有槽位都要单独占地址,不能把它当成一份Tile计算。 | ||
| 93 | + | ||
| 94 | +不同逻辑Tile可以复用同一物理区间,但必须同时满足以下条件: | ||
| 95 | + | ||
| 96 | +1. 两者位于同一MemorySpace,且被复用区间能容纳两者各自的完整物理占用; | ||
| 97 | +2. 生命周期不重叠,或者已有明确的同步保证新写入不会覆盖未完成的读取; | ||
| 98 | +3. 需要`auto_mutex`保护的核内跨Pipe依赖通过共享的`mutex_id`关系表达;未配置mutex元数据时,设计中必须给出对应的手工核内同步; | ||
| 99 | +4. 跨Cube/Vector Section的复用由R6的cross-core READY/RELEASE协议保护,`mutex_id`不能替代`event_id`。 | ||
| 100 | + | ||
| 101 | +不能证明上述条件时,地址必须分开。不同layout的Tile共用地址不是一种自动转换;只有对应API确实以新layout解释同一物理数据,且字节范围与生命周期均安全时,才能在设计中明示为别名复用。 | ||
| 102 | + | ||
| 103 | +### `mutex_id`与地址的关系 | ||
| 104 | + | ||
| 105 | +`mutex_ids`是Tile的同步元数据,不是内存分配器。它不决定Tile的地址、大小或槽位数,也不会检测容量超限。 | ||
| 106 | + | ||
| 107 | +当前实现要求`mutex_id`位于`[0, 31]`;同一Tile内的多个ID不能重复,同一TileGroup中每个Tile携带的ID数量必须相同。不同Tile之间允许复用ID,因此不能写成“kernel内必须全局唯一”。是否共享ID应由真实互斥关系决定。 | ||
| 108 | + | ||
| 109 | +## 5. 逐空间检查容量 | ||
| 110 | + | ||
| 111 | +对每个MemorySpace,将地址表中的物理区间合并后计算峰值占用。对于从0开始的连续排布,占用上界就是最大区间终点;存在地址空洞时,同时记录“有效字节数”和“最高地址上界”。容量校验使用最高地址上界,不能只把各Tile大小相加后忽略空洞。 | ||
| 112 | + | ||
| 113 | +以当前`pypto_cann` A5仿真平台配置为例,950PR/950DT的主要容量快照如下。这些数值用于理解和交叉检查,设计仍必须使用`EXPLORE_REPORT.md` §7中与当前产品和环境一致的探测值。 | ||
| 114 | + | ||
| 115 | +| MemorySpace | A5配置快照 | 字节数 | | ||
| 116 | +|---|---:|---:| | ||
| 117 | +| `Vec` | 248 KiB | 253952 | | ||
| 118 | +| `Mat` | 512 KiB | 524288 | | ||
| 119 | +| `Left` | 64 KiB | 65536 | | ||
| 120 | +| `Right` | 64 KiB | 65536 | | ||
| 121 | +| `Acc` | 256 KiB | 262144 | | ||
| 122 | +| `ScaleLeft` | 4 KiB逻辑地址域 | 4096 | | ||
| 123 | +| `ScaleRight` | 4 KiB逻辑地址域 | 4096 | | ||
| 124 | + | ||
| 125 | +`Scaling`的可用容量和具体分区与产品/API路径有关,必须从当次平台探测和对应API文档取值,本文不给出通用常量。 | ||
| 126 | + | ||
| 127 | +一个空间通过当且仅当: | ||
| 128 | + | ||
| 129 | +```text | ||
| 130 | +0 <= 每个物理区间的起始地址 | ||
| 131 | +所有并存区间不冲突,或重叠处有完整的复用证明 | ||
| 132 | +max(addr + size) <= 该MemorySpace的当次探测容量 | ||
| 133 | +``` | ||
| 134 | + | ||
| 135 | +超限时先清理不必要的地址空洞和重复预留,再依据生命周期寻找安全复用。仍然超限时回退R2调整Tile shape、缓冲深度或中间量保留时间;若主要占用来自API强制的临时空间,再回退R1更换API链。拆成多次kernel调用会改变整体方案,不应作为R3内的默认修复。 | ||
| 136 | + | ||
| 137 | +## 6. MX scale地址映射 | ||
| 138 | + | ||
| 139 | +`ScaleLeft`和`ScaleRight`虽然拥有独立的4 KiB逻辑地址域,但它们的起始地址不能独立选择。每个MX data/scale槽位必须逐项满足: | ||
| 140 | + | ||
| 141 | +```text | ||
| 142 | +ScaleLeftAddr[i] = LeftAddr[i] >> 4 | ||
| 143 | +ScaleRightAddr[i] = RightAddr[i] >> 4 | ||
| 144 | +``` | ||
| 145 | + | ||
| 146 | +例如`Left` group的两个地址为`[0x0000, 0x8000]`,对应`ScaleLeft` group必须为`[0x0000, 0x0800]`。该映射是硬件寻址约束,不是可选的bank优化。ScaleLeft/ScaleRight的4 KiB不从Left/Right的64 KiB数据空间中扣除。 | ||
| 147 | + | ||
| 148 | +## 7. L1 Bank冲突检查 | ||
| 149 | + | ||
| 150 | +容量、对齐和生命周期检查通过后,对Mat地址做L1 Bank检查。Ascend 950PR/950DT的L1为16个32 KiB Bank,组成8个Bank Group;地址位域和读写冲突规则见: | ||
| 151 | + | ||
| 152 | +`$PYPTO_DEVKIT_DIR/docs/pypto_pro/tutorials/operator_development/tile_based_python_programming/Cube_matrix_computation.md` | ||
| 153 | + | ||
| 154 | +R3只对计划并行访问的L1 Tile做这项检查。应根据实际`load`/`move`并行关系和地址位域判断,不能仅看两个Tile的基地址不同就宣称“无Bank冲突”。若官方指定样例与目标算子具有相同的Tile shape和访问方式,可借鉴其地址分组;仍需在本设计的地址表上重新验证。 | ||
| 155 | + | ||
| 156 | +## 8. DESIGN.md记录格式 | ||
| 157 | + | ||
| 158 | +每个物理槽位单独一行。单槽TileGroup也要标出`slot=0`,scratch Tile的槽位列写`—`。 | ||
| 159 | + | ||
| 160 | +| 空间 | 变量 | 槽位 | 用途 | shape | dtype | layout | 起始地址 | 大小(B) | 区间 | 生命周期/复用依据 | | ||
| 161 | +|---|---|---:|---|---|---|---|---:|---:|---|---| | ||
| 162 | +| Vec | `a_group` | 0 | 输入ping | `[64,128]` | FP16 | `—` | `0x00000` | 16384 | `[0x00000,0x04000)` | 迭代`2k` | | ||
| 163 | +| Vec | `a_group` | 1 | 输入pong | `[64,128]` | FP16 | `—` | `0x04000` | 16384 | `[0x04000,0x08000)` | 迭代`2k+1` | | ||
| 164 | +| Mat | `a_l1` | 0 | A矩阵暂存 | `[128,128]` | FP16 | NZ | `0x00000` | 32768 | `[0x00000,0x08000)` | K循环当前槽 | | ||
| 165 | +| Acc | `acc` | 0 | 累加结果 | `[128,128]` | FP32 | NZ | `0x00000` | 65536 | `[0x00000,0x10000)` | 完整K循环 | | ||
| 166 | + | ||
| 167 | +`—`表示未显式设置layout,由`TileType`按当前平台和MemorySpace应用默认值;它不表示“没有layout语义”。非默认layout必须显式写出。 | ||
| 168 | + | ||
| 169 | +地址表后按空间记录: | ||
| 170 | + | ||
| 171 | +```text | ||
| 172 | +Vec: 有效预留 ... B;最高地址上界 ... B / 容量 ... B = ...% | ||
| 173 | +Mat: 有效预留 ... B;最高地址上界 ... B / 容量 ... B = ...% | ||
| 174 | +Left/Right/Acc/...: 同样逐空间记录 | ||
| 175 | +``` | ||
| 176 | + | ||
| 177 | +若存在地址复用,再增加复用表: | ||
| 178 | + | ||
| 179 | +| 物理区间 | 逻辑Tile A | 逻辑Tile B | A最后读 | B首次写 | 保护机制 | 结论 | | ||
| 180 | +|---|---|---|---|---|---|---| | ||
| 181 | +| `Vec [0x...,0x...)` | `...` | `...` | `...` | `...` | 共享mutex / 手工核内sync / R6 cross-core事件 | 可复用/不可复用 | | ||
| 182 | + | ||
| 183 | +## R3完成检查 | ||
| 184 | + | ||
| 185 | +提交R3前逐项确认: | ||
| 186 | + | ||
| 187 | +- R2的每个Tile都能在地址表中找到,TileGroup的所有槽位已展开。 | ||
| 188 | +- 每个地址和`size`均为编译期整数,区间统一按`[addr, addr + size)`记录。 | ||
| 189 | +- 每个槽位的首地址满足对应MemorySpace的对齐要求。 | ||
| 190 | +- 分形、RowPlusOne、显式`size`和亚字节dtype的物理占用没有套用错误的普通公式。 | ||
| 191 | +- 同一MemorySpace内的并存区间不重叠;每个有意复用都有生命周期和同步证明。 | ||
| 192 | +- 容量使用当次`EXPLORE_REPORT.md` §7的平台值,并以最高地址上界而非仅Tile大小之和校验。 | ||
| 193 | +- MX路径的data/scale地址按槽位满足`scale_addr = data_addr >> 4`。 | ||
| 194 | +- 计划并行访问的L1 Tile已按官方L1 Bank位域和读写规则检查。 | ||
| 195 | +- `mutex_id`只表达核内跨Pipe互斥;cross-core `event_id`由R6单独设计。 | ||