已合并
【CANN社区任务】aclnnBernoulli算子设计文档 #671
hzw_rpap创建于 7月25日
【CANN社区任务】aclnnBernoulli算子设计文档 #671
已合并
共 1 个文件变更+540-0
| @@ -0,0 +1,540 @@ | |||
| 1 | +# aclnnBernoulli 算子内存优化设计文档 | ||
| 2 | + | ||
| 3 | +## 1. 需求背景(required) | ||
| 4 | + | ||
| 5 | +### 1.1 需求来源 | ||
| 6 | + | ||
| 7 | +- 任务名称:`7月社区任务-aclnnBernoulli算子开发` | ||
| 8 | +- 任务依据:[aclnnBernoulli 任务书](../../../../docs/202607/aclnnBernoulli_task_doc.md) | ||
| 9 | +- 目标产品:Atlas A2/A3 训练系列产品 | ||
| 10 | +- 软件版本:CANN 8.5.0 及以上 | ||
| 11 | +- 开发语言:Ascend C | ||
| 12 | + | ||
| 13 | +本任务要求在不改变 `aclnnBernoulli` 对外功能的前提下,优化 A2/A3 | ||
| 14 | +标量概率路径的设备内存占用,使其与等价 GPU 调用的内存差距小于 5%, | ||
| 15 | +同时保证性能不低于原实现。 | ||
| 16 | + | ||
| 17 | +### 1.2 算子功能 | ||
| 18 | + | ||
| 19 | +`aclnnBernoulli` 根据 `self` 的 shape、dtype 和布局生成独立 Bernoulli | ||
| 20 | +样本。`self` 的数值不参与计算,随机流由 `seed` 和 `offset` 决定。 | ||
| 21 | + | ||
| 22 | +对每个逻辑位置 `i`: | ||
| 23 | + | ||
| 24 | +```text | ||
| 25 | +out[i] ∈ {0, 1} | ||
| 26 | +P(out[i] = 1) = prob | ||
| 27 | +``` | ||
| 28 | + | ||
| 29 | +接口同时支持 out-of-place 和 inplace 调用。输出为浮点、整数或 `BOOL` | ||
| 30 | +时,均写入对应 dtype 可精确表示的 0 或 1。 | ||
| 31 | + | ||
| 32 | +### 1.3 接口能力与约束 | ||
| 33 | + | ||
| 34 | +| 参数 | 类型 | 支持范围 | 约束 | | ||
| 35 | +| --- | --- | --- | --- | | ||
| 36 | +| `self` | `aclTensor*` | FP16、FP32、FP64、BF16、UINT8、INT8、INT16、INT32、INT64、BOOL | ND;0~8 维;可为空、连续或非连续 | | ||
| 37 | +| `prob` | `aclScalar*` | FP16、FP32、FP64、BF16 | 有限值,且 `0 <= prob <= 1` | | ||
| 38 | +| `seed` | `int64_t` | INT64 | 用于确定随机流 | | ||
| 39 | +| `offset` | `int64_t` | INT64 | `offset % 4 == 0` | | ||
| 40 | +| `out` | `aclTensor*` | 与 `self` 相同 | shape、dtype 与 `self` 一致;可为非连续 Tensor | | ||
| 41 | + | ||
| 42 | +本次优化针对标量 `prob` 接口。Tensor-probability 接口不进入自定义融合 | ||
| 43 | +路径,继续沿用原有实现。 | ||
| 44 | + | ||
| 45 | +### 1.4 原实现与问题分析 | ||
| 46 | + | ||
| 47 | +CANN 8.5.0 中 A2/A3 标量概率的一般路径位于: | ||
| 48 | + | ||
| 49 | +```text | ||
| 50 | +random/dsa_gen_bit_mask/op_host/op_api/aclnn_bernoulli.cpp | ||
| 51 | +``` | ||
| 52 | + | ||
| 53 | +其执行链路为: | ||
| 54 | + | ||
| 55 | +```text | ||
| 56 | +Contiguous(self) | ||
| 57 | + -> DSAGenBitMask | ||
| 58 | + -> Fill(ones) | ||
| 59 | + -> DropoutDoMask | ||
| 60 | + -> Cast(target dtype) | ||
| 61 | + -> ViewCopy(out) | ||
| 62 | +``` | ||
| 63 | + | ||
| 64 | +设输出元素数为 `N`,目标 dtype 字节数为 `B`,DSA 生成的 packed mask | ||
| 65 | +大小为: | ||
| 66 | + | ||
| 67 | +```text | ||
| 68 | +M = ceil(N / 128) * 16 = align_up(N, 128) / 8 | ||
| 69 | +``` | ||
| 70 | + | ||
| 71 | +原链路除 packed mask 外,还会产生全 shape 的 ones、mask 展开结果以及 | ||
| 72 | +部分 dtype 下的 Cast 结果。主要逻辑中间值如下: | ||
| 73 | + | ||
| 74 | +| 中间值 | shape / dtype | 逻辑字节数 | | ||
| 75 | +| --- | --- | ---: | | ||
| 76 | +| packed mask | `uint8[M]` | `M` | | ||
| 77 | +| `inputOnes` | 全 shape,FP16 或 FP32 | `N×2` 或 `N×4` | | ||
| 78 | +| `doMaskOut` | 与 `inputOnes` 相同 | `N×2` 或 `N×4` | | ||
| 79 | +| Cast 结果 | 目标 dtype | 最多 `N×B` | | ||
| 80 | +| 非连续输入的连续副本 | 目标 dtype | `N×B` | | ||
| 81 | + | ||
| 82 | +执行器可能复用不同逻辑节点的存储,因此不能把表中各项直接相加作为峰值; | ||
| 83 | +但这些随 `N` 线性增长的中间 Tensor 会显著增加 workspace 和 GM 流量。 | ||
| 84 | +以 A2/A3、shape `[4096,4096]`、`prob=0.5` 为例,原 ACLNN workspace | ||
| 85 | +在两个平台上的结果一致: | ||
| 86 | + | ||
| 87 | +| dtype | 原 workspace | | ||
| 88 | +| --- | ---: | | ||
| 89 | +| FP16 / BF16 | 35,652,608 B | | ||
| 90 | +| FP32 | 69,207,040 B | | ||
| 91 | +| INT64 / FP64 | 69,207,552 B | | ||
| 92 | + | ||
| 93 | +因此,本任务的核心不是更换随机数算法,而是在保留 DSA 随机流的同时, | ||
| 94 | +消除 `Fill + DropoutDoMask + Cast` 引入的全 shape 中间值。 | ||
| 95 | + | ||
| 96 | +## 2. 需求分析(required) | ||
| 97 | + | ||
| 98 | +### 2.1 设计目标 | ||
| 99 | + | ||
| 100 | +1. 保持公共 ACLNN 签名、两阶段调用方式和返回语义不变。 | ||
| 101 | +2. 覆盖任务书要求的全部 dtype、0~8 维、空 Tensor、连续与非连续布局。 | ||
| 102 | +3. 保留 `prob=0`、`prob=1` 快路径及 `seed/offset` 随机状态语义。 | ||
| 103 | +4. 连续 dense 输出不再申请随 shape 增长的全量中间 Tensor。 | ||
| 104 | +5. 非连续 Tensor、非零 storage offset 和特殊 storage/view 关系不得越界写。 | ||
| 105 | +6. A2 与 A3 使用同一份 Ascend C 源码,硬件资源通过 Tiling 运行时查询。 | ||
| 106 | +7. 新实现性能不低于原实现,并按等价调用协议完成 NPU/GPU 内存对比。 | ||
| 107 | + | ||
| 108 | +### 2.2 外部依赖 | ||
| 109 | + | ||
| 110 | +本方案不引入新的第三方组件,复用 CANN 已有能力: | ||
| 111 | + | ||
| 112 | +| 依赖 | 用途 | | ||
| 113 | +| --- | --- | | ||
| 114 | +| `DSAGenBitMask` | 生成与原实现一致的 packed 随机 mask | | ||
| 115 | +| Ascend C Vector API | 在 UB 内完成 mask 展开、Select、Cast 和 Gather | | ||
| 116 | +| `ZerosLike` / `OnesLike` | 处理 `prob=0/1` 精确快路径 | | ||
| 117 | +| `ViewCopy` | 将连续临时结果写回非连续逻辑 view | | ||
| 118 | +| `PlatformAscendC` | 查询 UB 容量和 Vector Core 数量 | | ||
| 119 | + | ||
| 120 | +### 2.3 方案比较 | ||
| 121 | + | ||
| 122 | +| 方案 | 内存效果 | 随机语义风险 | 实现风险 | 结论 | | ||
| 123 | +| --- | --- | --- | --- | --- | | ||
| 124 | +| 仅对旧 `Fill/DropoutDoMask` 做存储别名 | 仍保留多 Kernel 和部分全量中间值 | 低 | dtype、别名和非连续布局约束复杂 | 不采用 | | ||
| 125 | +| 单 Kernel 自行实现 RNG 和写出 | 可完全融合 | 高,需要重新证明 seed/offset 消耗和统计质量 | A2/A3 无可直接复用的 Philox API | 不采用 | | ||
| 126 | +| 保留 DSA,新增 packed mask 展开 Kernel | 连续路径无全 shape 临时值 | 低,可保持原 DSA 随机流 | 需要证明同址展开安全 | 采用 | | ||
| 127 | + | ||
| 128 | +最终方案为: | ||
| 129 | + | ||
| 130 | +```text | ||
| 131 | +DSAGenBitMask(mask aliases dense out) | ||
| 132 | + -> BernoulliMask(high-to-low waves) | ||
| 133 | + -> out | ||
| 134 | +``` | ||
| 135 | + | ||
| 136 | +对于不满足同址条件的输出,采用独立 packed mask 和连续输出临时值作为 | ||
| 137 | +fallback,以保证通用布局语义。 | ||
| 138 | + | ||
| 139 | +## 3. 详细设计(required) | ||
| 140 | + | ||
| 141 | +### 3.1 总体设计 | ||
| 142 | + | ||
| 143 | +`BernoulliMask` 是新增的 Ascend C L0 算子。它不读取 `self` 的数据, | ||
| 144 | +只读取 DSA 生成的 packed mask,并在 UB 内将每个 bit 展开为目标 dtype | ||
| 145 | +的 0/1。 | ||
| 146 | + | ||
| 147 | +根据输出布局和容量,Host 侧选择三条路径: | ||
| 148 | + | ||
| 149 | +```text | ||
| 150 | + +--> prob=0/1: ZerosLike / OnesLike | ||
| 151 | + | | ||
| 152 | +aclnnBernoulli ----------+--> 一般概率 + 可安全同址 | ||
| 153 | + | DSA(mask写入out起始区) | ||
| 154 | + | -> BernoulliMask原地展开 | ||
| 155 | + | | ||
| 156 | + +--> 一般概率 + 不可同址 | ||
| 157 | + 独立mask -> 连续结果 | ||
| 158 | + -> ViewCopy(out) | ||
| 159 | +``` | ||
| 160 | + | ||
| 161 | +### 3.2 Host 侧设计 | ||
| 162 | + | ||
| 163 | +#### 3.2.1 参数校验与特殊路径 | ||
| 164 | + | ||
| 165 | +Phase 1 按以下顺序处理: | ||
| 166 | + | ||
| 167 | +1. 校验 `self`、`prob`、`out`、`workspaceSize` 和 `executor` 非空。 | ||
| 168 | +2. 校验 `self/out` 的 dtype、shape 和 format,并限制 rank 不超过 8。 | ||
| 169 | +3. 校验 `prob` 为有限值且位于 `[0,1]`。 | ||
| 170 | +4. 校验 `offset % 4 == 0`。 | ||
| 171 | +5. 空 Tensor 返回 `workspaceSize=0`,不下发 Kernel。 | ||
| 172 | +6. `prob=0` 调用 `ZerosLike`,`prob=1` 调用 `OnesLike`。 | ||
| 173 | +7. 其他概率进入 DSA + `BernoulliMask` 路径。 | ||
| 174 | + | ||
| 175 | +#### 3.2.2 Dense alias 判定 | ||
| 176 | + | ||
| 177 | +仅当以下条件全部满足时,packed mask 才允许与用户 `out` 共用存储: | ||
| 178 | + | ||
| 179 | +1. `out` 为标准行主序连续布局,stride 与 shape 完全匹配; | ||
| 180 | +2. view offset 和 storage offset 均为 0; | ||
| 181 | +3. 逻辑 view 恰好覆盖整个底层 storage,即二者元素数相等; | ||
| 182 | +4. 输出容量满足 `N×B >= M`; | ||
| 183 | +5. Tensor format 不是私有格式。 | ||
| 184 | + | ||
| 185 | +第 3 条用于保护“连续小 view + 更大 backing storage”的场景。即使该 | ||
| 186 | +view 本身连续,也不能让原地 Kernel 写入 view 之外的 guard 区域。 | ||
| 187 | + | ||
| 188 | +满足条件时,Host 在 `out` 起始地址上建立 `UINT8[M]` view,作为 | ||
| 189 | +`DSAGenBitMask` 的输出。由于 mask 和最终输出属于同一 GM allocation, | ||
| 190 | +连续 dense 路径无需独立 packed-mask Tensor。 | ||
| 191 | + | ||
| 192 | +由于 DSA mask 按 128 bit 对齐,极小 Tensor 可能不满足容量条件。对于 | ||
| 193 | +1/2/4/8 字节输出,允许同址的最小元素数分别为 16/8/4/2;更小输入走 | ||
| 194 | +独立 mask fallback。 | ||
| 195 | + | ||
| 196 | +#### 3.2.3 Fallback 与 FP64 非连续写回 | ||
| 197 | + | ||
| 198 | +下列场景使用保守 fallback: | ||
| 199 | + | ||
| 200 | +- 非连续输出; | ||
| 201 | +- view/storage offset 非零; | ||
| 202 | +- 逻辑 view 未覆盖完整 storage; | ||
| 203 | +- 极小 Tensor 容量不足; | ||
| 204 | +- 不支持直接解释的私有格式直接在参数校验阶段拒绝。 | ||
| 205 | + | ||
| 206 | +fallback 路径为: | ||
| 207 | + | ||
| 208 | +```text | ||
| 209 | +DSAGenBitMask(independent mask) | ||
| 210 | + -> BernoulliMask(continuous temporary) | ||
| 211 | + -> ViewCopy(out) | ||
| 212 | +``` | ||
| 213 | + | ||
| 214 | +A2 的 `ViewCopy` 路径未直接声明 FP64 支持。对于非连续 FP64 输出,Host | ||
| 215 | +为源和目标建立保持 shape、stride 和 offset 的 INT64 bit-view,再执行 | ||
| 216 | +`ViewCopy`。该过程只搬运 64-bit 位模式,不进行数值转换。 | ||
| 217 | + | ||
| 218 | +#### 3.2.4 架构分流 | ||
| 219 | + | ||
| 220 | +A2/A3 对应的 DAV_2201 路径进入本次 DSA 融合实现。DAV_3510 及其他 | ||
| 221 | +非目标架构继续沿用 `StatelessBernoulli` 路径,避免改变非目标产品行为。 | ||
| 222 | + | ||
| 223 | +### 3.3 Tiling 设计 | ||
| 224 | + | ||
| 225 | +#### 3.3.1 TilingData | ||
| 226 | + | ||
| 227 | +TilingData 只传递 Kernel 必需的信息: | ||
| 228 | + | ||
| 229 | +```text | ||
| 230 | +totalElements | ||
| 231 | +elementsPerCore | ||
| 232 | +tileElements | ||
| 233 | +maskAliasesOut | ||
| 234 | +``` | ||
| 235 | + | ||
| 236 | +Host 通过 `PlatformAscendC` 动态获取 UB 大小和 Vector Core 数,不硬编码 | ||
| 237 | +A2/A3 的资源参数。 | ||
| 238 | + | ||
| 239 | +#### 3.3.2 分块与分核 | ||
| 240 | + | ||
| 241 | +设输出元素宽度为 `B`,预留 UB 为 8 KiB。Host 以 4-byte work buffer | ||
| 242 | +和保守的 1-byte mask 开销估算单元素空间: | ||
| 243 | + | ||
| 244 | +```text | ||
| 245 | +bytesPerElement = B + 4 + 1 | ||
| 246 | +tileElements = align_down((UB - 8 KiB) / bytesPerElement, 256) | ||
| 247 | +tileElements = min(tileElements, 16384) | ||
| 248 | +blockDim = min(vectorCoreNum, ceil(totalElements / tileElements)) | ||
| 249 | +elementsPerCore = align_up(ceil(totalElements / blockDim), 256) | ||
| 250 | +``` | ||
| 251 | + | ||
| 252 | +小 shape 自动减少核数;大 shape 在 A2 上使用 40 个 Vector Core。 | ||
| 253 | +fallback 路径中,各核处理互不重叠的连续元素区间。 | ||
| 254 | + | ||
| 255 | +当 `maskAliasesOut=1` 时,Host 设置 `SetScheduleMode(1)`。该模式保证 | ||
| 256 | +所有已启动核心以一致的同步轮次执行高到低 wave,避免核间提前覆盖尚未 | ||
| 257 | +读取的 mask。 | ||
| 258 | + | ||
| 259 | +#### 3.3.3 TilingKey | ||
| 260 | + | ||
| 261 | +| Key | 输出 dtype | Kernel 实例 | | ||
| 262 | +| ---: | --- | --- | | ||
| 263 | +| 1 | FP16 | `half` | | ||
| 264 | +| 2 | FP32 | `float` | | ||
| 265 | +| 3 | FP64 | `uint64_t` 位模式,Select + Gather | | ||
| 266 | +| 4 | UINT8 / BOOL | `uint8_t` | | ||
| 267 | +| 5 | INT8 | `int8_t` | | ||
| 268 | +| 6 | INT16 | `int16_t` | | ||
| 269 | +| 7 | INT32 | `int32_t` | | ||
| 270 | +| 8 | INT64 | `int64_t` | | ||
| 271 | +| 9 | BF16 | `bfloat16_t` | | ||
| 272 | + | ||
| 273 | +### 3.4 Kernel 侧设计 | ||
| 274 | + | ||
| 275 | +#### 3.4.1 单 tile 执行流程 | ||
| 276 | + | ||
| 277 | +每个 tile 依次执行: | ||
| 278 | + | ||
| 279 | +1. 使用 `DataCopyPad` 将 `ceil(count/8)` 字节 packed mask 搬入 UB; | ||
| 280 | +2. 使用 `Select` 将 mask bit 展开为 FP16 或 FP32 的 0/1; | ||
| 281 | +3. 浮点结果直接写出,整数和 BF16 在 UB 内 Cast; | ||
| 282 | +4. FP64 使用 Select + Gather 组装 IEEE-754 64-bit 位模式; | ||
| 283 | +5. 仅搬出 `count×sizeof(T)` 个有效字节,不写对齐 padding。 | ||
| 284 | + | ||
| 285 | +各 dtype 的计算路径如下: | ||
| 286 | + | ||
| 287 | +| 类别 | dtype | UB 中间类型 | 写出策略 | | ||
| 288 | +| --- | --- | --- | --- | | ||
| 289 | +| 16-bit 浮点 | FP16 | FP16 | Select 后直接写出 | | ||
| 290 | +| 32-bit 浮点 | FP32 | FP32 | Select 后直接写出 | | ||
| 291 | +| 64-bit 浮点 | FP64 | 两个 FP32 word | Select high word,Gather 交织 | | ||
| 292 | +| 8-bit / BOOL | INT8、UINT8、BOOL | FP16 | Select 后 Cast | | ||
| 293 | +| 16-bit 整数 | INT16 | FP16 | `CAST_RINT` | | ||
| 294 | +| 32/64-bit 整数 | INT32、INT64 | FP32 | `CAST_TRUNC` | | ||
| 295 | +| BF16 | BF16 | FP32 | `CAST_RINT` | | ||
| 296 | + | ||
| 297 | +#### 3.4.2 同址展开安全性 | ||
| 298 | + | ||
| 299 | +packed mask 初始位于 `out` 的低地址区域。如果从低地址开始展开,输出 | ||
| 300 | +可能覆盖后续尚未读取的 mask。为此,alias 路径按高地址到低地址分 wave | ||
| 301 | +处理。 | ||
| 302 | + | ||
| 303 | +设尚未展开区间为 `[0, end)`,输出元素宽度为 `d` 字节,本轮起点为: | ||
| 304 | + | ||
| 305 | +```text | ||
| 306 | +start = align_up(ceil(ceil(end / 8) / d), 256) | ||
| 307 | +``` | ||
| 308 | + | ||
| 309 | +此时满足: | ||
| 310 | + | ||
| 311 | +```text | ||
| 312 | +d * start >= ceil(end / 8) | ||
| 313 | +``` | ||
| 314 | + | ||
| 315 | +因此 `[start,end)` 的输出写区域不会覆盖 `[0,ceil(end/8))` 中仍需读取 | ||
| 316 | +的 mask。所有核心完成当前 wave 后执行 `SyncAll`,再处理更低地址区间。 | ||
| 317 | +最后不超过 256 个元素的前缀由 core 0 先完整搬入 UB,再写回输出。 | ||
| 318 | + | ||
| 319 | +所有已启动核心必须参与相同次数的 `SyncAll`;即使某个核心在当前 wave | ||
| 320 | +没有有效输出,也不能提前返回。 | ||
| 321 | + | ||
| 322 | +#### 3.4.3 UB 预算 | ||
| 323 | + | ||
| 324 | +Kernel 采用单缓冲: | ||
| 325 | + | ||
| 326 | +```text | ||
| 327 | +maskQueue = align_up(ceil(tileElements / 8), 32) | ||
| 328 | +outQueue = align_up(tileElements * B, 32) | ||
| 329 | +workBuf = align_up(tileElements * 4, 32) | ||
| 330 | +UB_total = maskQueue + outQueue + workBuf | ||
| 331 | +``` | ||
| 332 | + | ||
| 333 | +以 A2 的 192 KiB UB 为例: | ||
| 334 | + | ||
| 335 | +| dtype 宽度 | tileElements | maskQueue | outQueue | workBuf | 总计 | | ||
| 336 | +| ---: | ---: | ---: | ---: | ---: | ---: | | ||
| 337 | +| 1 B | 16,384 | 2,048 B | 16,384 B | 65,536 B | 83,968 B | | ||
| 338 | +| 2 B | 16,384 | 2,048 B | 32,768 B | 65,536 B | 100,352 B | | ||
| 339 | +| 4 B | 16,384 | 2,048 B | 65,536 B | 65,536 B | 133,120 B | | ||
| 340 | +| 8 B | 14,336 | 1,792 B | 114,688 B | 57,344 B | 173,824 B | | ||
| 341 | + | ||
| 342 | +各路径均低于 UB 容量,并保留 8 KiB 预算。A3 使用相同公式按运行时资源 | ||
| 343 | +重新计算。当前版本不启用双缓冲,因为其会缩小单 tile,且现有 Profile | ||
| 344 | +未显示足以抵消该开销的收益。 | ||
| 345 | + | ||
| 346 | +### 3.5 内存与性能分析 | ||
| 347 | + | ||
| 348 | +#### 3.5.1 内存模型 | ||
| 349 | + | ||
| 350 | +| 指标 | 原实现 | 新实现(连续 dense) | | ||
| 351 | +| --- | --- | --- | | ||
| 352 | +| 主要链路 | DSA + Fill + DropoutDoMask + Cast + ViewCopy | DSA + BernoulliMask | | ||
| 353 | +| 全 shape GM 临时值 | 至少一个,随 dtype 和规划变化 | 0 | | ||
| 354 | +| packed mask | 独立分配 | 复用 `out` 起始存储 | | ||
| 355 | +| 全 shape 写出 | 多次 | 一次 `N×B` | | ||
| 356 | +| 非连续输出 | 连续化后多级中间值 | 一个连续结果 + ViewCopy | | ||
| 357 | + | ||
| 358 | +A2 和 A3 在 `[4096,4096]` 一般概率路径上的 workspace 结果一致: | ||
| 359 | + | ||
| 360 | +| dtype | 原 workspace | 新 workspace | 减少比例 | | ||
| 361 | +| --- | ---: | ---: | ---: | | ||
| 362 | +| FP16 / BF16 | 35,652,608 B | 1,024 B | 99.997% | | ||
| 363 | +| FP32 | 69,207,040 B | 1,024 B | 99.999% | | ||
| 364 | +| INT64 / FP64 | 69,207,552 B | 1,024 B | 99.999% | | ||
| 365 | + | ||
| 366 | +workspace 结果用于证明算子内部随 shape 增长的临时值已被消除;最终 | ||
| 367 | +NPU/GPU 内存一致性仍以等价框架调用的进程峰值为准,不能用 workspace | ||
| 368 | +降幅替代。 | ||
| 369 | + | ||
| 370 | +#### 3.5.2 测试对象与证据绑定 | ||
| 371 | + | ||
| 372 | +A2/A3 实测使用同一源码版本,结果分别绑定目标平台包和实际加载的 | ||
| 373 | +custom DSO: | ||
| 374 | + | ||
| 375 | +| 对象 | 环境 | 版本标识 | 主证据 | | ||
| 376 | +| --- | --- | --- | --- | | ||
| 377 | +| 源码 | `experimental/random/bernoulli_mask` | commit `295d1e7fe793d3e5477d00cd1af86ebcea770f1d` | 算子 tree `db92e5b6d2999518723f231804d8c8a6202bacad` | | ||
| 378 | +| A2 | Ascend 910B4,CANN 8.5.2 | package SHA-256 `06e71eca975f1ac8735352071e9984a35891ebceb1b6a3304b0d442ea111419a` | `results/*/20260725-p0-guard-hardening-final-a2-*` | | ||
| 379 | +| A3 | Ascend910_9362,CANN 8.5.2,构建目标 `ascend910_93` | package SHA-256 `05040ef871a62bff8d66a43a098460fbfcd0990a5a24586dcd8e7b50d1d42029` | `results/a3/a3-final-007/` | | ||
| 380 | +| GPU | NVIDIA H800 MIG | B011~B014,各 20 个隔离进程 | `results/gpu/20260725-h800-mig-torch-bernoulli/` | | ||
| 381 | + | ||
| 382 | +#### 3.5.3 A2/A3 与 GPU 内存对比 | ||
| 383 | + | ||
| 384 | +三个平台采用相同 `[8192,8192]` shape、dtype、`prob=0.5`、inplace | ||
| 385 | +`Tensor.bernoulli_` 调用层级和隔离进程协议。A2、A3 各完成 direct | ||
| 386 | +ACLNN old/new 160 条和 torch-npu old/new 160 条记录;GPU 完成 4 个 | ||
| 387 | +case、每 case 20 条记录。下表为中位 total peak: | ||
| 388 | + | ||
| 389 | +| Case | dtype | 指标 | H800 MIG | A2 | A2/GPU 差距 | A3 | A3/GPU 差距 | | ||
| 390 | +| --- | --- | --- | ---: | ---: | ---: | ---: | ---: | | ||
| 391 | +| B011 | FP32 | allocated | 268,435,456 B | 268,437,504 B | 0.000763% | 268,437,504 B | 0.000763% | | ||
| 392 | +| B011 | FP32 | reserved | 268,435,456 B | 272,629,760 B | 1.5625% | 272,629,760 B | 1.5625% | | ||
| 393 | +| B012 | FP16 | allocated | 134,217,728 B | 134,219,776 B | 0.001526% | 134,219,776 B | 0.001526% | | ||
| 394 | +| B012 | FP16 | reserved | 134,217,728 B | 138,412,032 B | 3.1250% | 138,412,032 B | 3.1250% | | ||
| 395 | +| B013 | INT64 | allocated | 536,870,912 B | 536,872,960 B | 0.000381% | 536,872,960 B | 0.000381% | | ||
| 396 | +| B013 | INT64 | reserved | 536,870,912 B | 541,065,216 B | 0.7813% | 541,065,216 B | 0.7813% | | ||
| 397 | +| B014 | BF16 | allocated | 134,217,728 B | 134,219,776 B | 0.001526% | 134,219,776 B | 0.001526% | | ||
| 398 | +| B014 | BF16 | reserved | 134,217,728 B | 138,412,032 B | 3.1250% | 138,412,032 B | 3.1250% | | ||
| 399 | + | ||
| 400 | +A2、A3 的四个 case 在 total peak allocated 和 reserved 两种可定义 | ||
| 401 | +口径下均小于 5%。同一 inplace 协议下,A2/A3 的 incremental peak | ||
| 402 | +allocated 中位数为 1,536 B、reserved 为 2,097,152 B,GPU 两项均为 | ||
| 403 | +0 B,因此增量百分比的分母为 0。报告保留原始字节数并将百分比标记为 | ||
| 404 | +`undefined`,不将其改写为 0%。 | ||
| 405 | + | ||
| 406 | +#### 3.5.4 A2/A3 性能结果 | ||
| 407 | + | ||
| 408 | +两个平台均对 5 种 dtype 的 old/new 各执行 20 个隔离进程;每个进程 | ||
| 409 | +预热 10 次,再进行 100 次 device event 计时。每个平台 200/200 条记录 | ||
| 410 | +成功,且每组 old/new 输出 hash 一致。 | ||
| 411 | + | ||
| 412 | +**A2 性能:** | ||
| 413 | + | ||
| 414 | +| dtype | 原/新 P50 (ms) | 原/新 P90 (ms) | P50 改善 | | ||
| 415 | +| --- | ---: | ---: | ---: | | ||
| 416 | +| FP16 | 0.236425 / 0.221500 | 0.241940 / 0.227110 | 6.313% | | ||
| 417 | +| FP32 | 0.396570 / 0.229040 | 0.405220 / 0.233360 | 42.245% | | ||
| 418 | +| BF16 | 0.256160 / 0.228795 | 0.264550 / 0.234860 | 10.683% | | ||
| 419 | +| INT64 | 0.517965 / 0.379865 | 0.524110 / 0.385890 | 26.662% | | ||
| 420 | +| FP64 | 34.954804 / 0.393395 | 35.015261 / 0.400220 | 98.875% | | ||
| 421 | + | ||
| 422 | +**A3 性能:** | ||
| 423 | + | ||
| 424 | +| dtype | 原/新 P50 (ms) | 原/新 P90 (ms) | P50 改善 | | ||
| 425 | +| --- | ---: | ---: | ---: | | ||
| 426 | +| FP16 | 0.210415 / 0.191985 | 0.213310 / 0.197960 | 8.759% | | ||
| 427 | +| FP32 | 0.287395 / 0.200915 | 0.290620 / 0.207110 | 30.091% | | ||
| 428 | +| BF16 | 0.226400 / 0.201440 | 0.229470 / 0.207100 | 11.025% | | ||
| 429 | +| INT64 | 0.341265 / 0.264750 | 0.343050 / 0.271180 | 22.421% | | ||
| 430 | +| FP64 | 34.992384 / 0.341385 | 35.031490 / 0.346200 | 99.024% | | ||
| 431 | + | ||
| 432 | +A2/A3 的 P50、P90 均未出现性能回退。FP64 的主要收益来自 UB 内 | ||
| 433 | +Select + Gather,避免原路径的低效 64-bit 标量构造和多级中间值。 | ||
| 434 | + | ||
| 435 | +### 3.6 支持硬件 | ||
| 436 | + | ||
| 437 | +| 芯片版本 | 支持情况 | 验证情况 | | ||
| 438 | +| --- | :---: | --- | | ||
| 439 | +| Atlas 800I/T A2,`ascend910b` | √ | 已完成核心验收矩阵、TTK 和 Sanitizer | | ||
| 440 | +| Atlas A3 训练系列,`ascend910_93` | √ | 已完成同等的核心验收矩阵、TTK 和 Sanitizer | | ||
| 441 | + | ||
| 442 | +### 3.7 算子约束与设计边界 | ||
| 443 | + | ||
| 444 | +1. 不新增用户可见约束,公共 shape、dtype、layout 和随机参数语义保持不变。 | ||
| 445 | +2. 本次融合仅替换 A2/A3 标量概率的一般概率路径。 | ||
| 446 | +3. Tensor-probability 接口继续沿用原路径。 | ||
| 447 | +4. 非连续或不满足完整 storage 覆盖条件的输出需要连续临时值和 ViewCopy。 | ||
| 448 | +5. `offset` 按任务书要求校验为 4 的倍数。 | ||
| 449 | + | ||
| 450 | +## 4. 特性交叉分析 | ||
| 451 | + | ||
| 452 | +| 交叉场景 | 风险 | 设计处理 | | ||
| 453 | +| --- | --- | --- | | ||
| 454 | +| out-of-place × 连续 dense | packed mask 额外分配导致峰值增长 | mask 复用 `out` 起始存储 | | ||
| 455 | +| inplace × 连续 dense | mask 与最终输出同址覆盖 | 高到低 wave + `SyncAll` | | ||
| 456 | +| 连续 view × 更大 backing storage | Kernel 可能写到逻辑 view 外 | 仅当 view 元素数等于 storage 元素数时允许 alias | | ||
| 457 | +| 非连续 × 非零 offset | 物理地址与逻辑顺序不一致 | 连续临时结果 + ViewCopy | | ||
| 458 | +| FP64 × 非连续 | ViewCopy 不直接声明 DOUBLE 支持 | INT64 bit-view 搬运位模式 | | ||
| 459 | +| 极小 Tensor × mask 对齐 | 输出容量小于 16-byte mask | 独立 mask fallback | | ||
| 460 | +| 空 Tensor × Kernel 调度 | 无效下发或除零 | Phase 1 直接返回 workspace 0 | | ||
| 461 | +| `prob=0/1` × 随机路径 | 不必要的 DSA 和同步开销 | ZerosLike / OnesLike 快路径 | | ||
| 462 | +| A2 × A3 | UB 和核数不同 | `PlatformAscendC` 运行时查询 | | ||
| 463 | + | ||
| 464 | +## 5. 可维可测分析 | ||
| 465 | + | ||
| 466 | +### 5.1 验收标准 | ||
| 467 | + | ||
| 468 | +| 验收项 | 标准 | 验证方法 | | ||
| 469 | +| --- | --- | --- | | ||
| 470 | +| 功能 | 覆盖全部 dtype、rank 0~8、空/非连续/inplace 和边界参数 | ACLNN 功能矩阵、ST、Host UT、TTK | | ||
| 471 | +| 随机性 | 固定 seed/offset 可重现;改变状态后随机流改变;分布无退化 | checksum、Wilson 区间、双侧二项检验和 Holm 校正 | | ||
| 472 | +| 内存 | 与等价 GPU 调用的内存差距小于 5% | 同 shape/dtype/API 层级的隔离进程峰值对比 | | ||
| 473 | +| 性能 | 不低于原 A2/A3 实现 | 预热后 device event P50/P90 对比 | | ||
| 474 | +| 安全 | 不发生越界、竞争或同步错误 | guard-region 与 mem/race/init/sync Sanitizer | | ||
| 475 | + | ||
| 476 | +随机算子的一般概率输出不要求与 GPU 逐元素相同。固定 seed/offset 用于 | ||
| 477 | +验证 NPU 新旧实现的可重现性;跨平台正确性通过值域和统计检验判断。 | ||
| 478 | + | ||
| 479 | +### 5.2 覆盖矩阵与实测证据 | ||
| 480 | + | ||
| 481 | +#### 5.2.1 用例覆盖 | ||
| 482 | + | ||
| 483 | +| 验证维度 | 覆盖内容 | | ||
| 484 | +| --- | --- | | ||
| 485 | +| dtype | 10 种 `self/out` dtype,4 种 `prob` dtype | | ||
| 486 | +| shape | 0~8 维、空 Tensor、标量、对齐边界、小 shape 和大 shape | | ||
| 487 | +| layout | 连续、转置、切片、非零 offset、oversized storage guard | | ||
| 488 | +| 概率 | `0`、`1`、接近边界及一般概率 | | ||
| 489 | +| RNG | 相同/不同 seed,合法/不同/非法 offset | | ||
| 490 | +| 接口 | out-of-place、inplace、标量概率及 Tensor-probability 回归 | | ||
| 491 | +| 平台 | A2 与 A3 构建和实机验证 | | ||
| 492 | + | ||
| 493 | +#### 5.2.2 A2/A3 核心验收结果 | ||
| 494 | + | ||
| 495 | +核心验收项在 A2/A3 上采用对称矩阵和相同判据: | ||
| 496 | + | ||
| 497 | +| 验证项 | A2 | A3 | 结论 | | ||
| 498 | +| --- | ---: | ---: | --- | | ||
| 499 | +| ACLNN 功能矩阵 | 77/77 | 77/77 | 覆盖 10 dtype、rank 0~8、布局、概率、offset、inplace 和 guard | | ||
| 500 | +| ACLNN ST | 97/97 | 97/97 | 覆盖接口校验、重现性、alias/fallback 边界和异常参数 | | ||
| 501 | +| 固定状态重现与敏感性 | 通过 | 通过 | 相同 seed/offset checksum 相同,改变 seed 或 offset 后不同 | | ||
| 502 | +| 正式分布统计 | 15/15 | 15/15 | 99% Wilson、双侧精确二项检验和 Holm 校正均通过 | | ||
| 503 | +| 最大绝对 z 值 / 最小原始 p-value | 1.661061 / 0.097172 | 1.661061 / 0.097172 | 未发现随机分布退化 | | ||
| 504 | +| old/new 正式性能 | 200/200 | 200/200 | 5 种 dtype 的 P50/P90 均无回退,输出 hash 一致 | | ||
| 505 | +| direct ACLNN 内存 | 160/160 | 160/160 | B011~B014、old/new、每组 20 个隔离进程 | | ||
| 506 | +| torch-npu 内存 | 160/160 | 160/160 | 与 GPU 使用等价框架调用协议 | | ||
| 507 | +| NPU/GPU total peak | 4/4 `<5%` | 4/4 `<5%` | allocated 和 reserved 均满足阈值 | | ||
| 508 | +| Tensor-probability 兼容回归 | 8/8 | 8/8 | 验证系统 Tensor-probability API 未被自定义标量接口回归 | | ||
| 509 | + | ||
| 510 | +#### 5.2.3 工程与安全验证 | ||
| 511 | + | ||
| 512 | +TTK 与 Sanitizer 在 A2/A3 上使用相同用例和判定标准。Sanitizer | ||
| 513 | +单独使用与 Release 包同源的插桩包,不替代功能、性能和内存测试所用的 | ||
| 514 | +Release 包。 | ||
| 515 | + | ||
| 516 | +| 工具层级 | 结果 | 说明 | | ||
| 517 | +| --- | --- | --- | | ||
| 518 | +| A2 TTK Kernel | 通用 26/26 + 存储复用 8/8 | 性能、精度和越界检查均为 PASS | | ||
| 519 | +| A2 Sanitizer | 115 PASS、13 `LIMITED_MASKED_VSEL`、0 FAIL | 完整执行 128 项 memcheck/racecheck/initcheck/synccheck | | ||
| 520 | +| A3 TTK Kernel | 通用 26/26 + 存储复用 8/8 | 性能、精度和越界检查均为 PASS | | ||
| 521 | +| A3 Sanitizer | 115 PASS、13 `LIMITED_MASKED_VSEL`、0 FAIL | 完整执行 128 项 memcheck/racecheck/initcheck/synccheck | | ||
| 522 | + | ||
| 523 | +CANN 8.5 对 masked `Select` 的部分 initcheck 用例存在工具识别限制, | ||
| 524 | +因此 A2/A3 各有 13 项标记为 `LIMITED_MASKED_VSEL`。这些项目未计入 PASS; | ||
| 525 | +其余 115 项通过,未发现代码故障。 | ||
| 526 | + | ||
| 527 | +平台专项工程验证中,A2 AscendOpTest 使用默认阈值完成 2 个固定随机状态 | ||
| 528 | +用例,结果为 2/2 PASS;A3 Host UT 为 36/36 PASS,并完成 Basic Profile | ||
| 529 | +采集。A2/A3 的 TTK Kernel 精度检查均为 34/34 PASS。 | ||
| 530 | + | ||
| 531 | +### 5.3 兼容性分析 | ||
| 532 | + | ||
| 533 | +- 保留 `aclnnBernoulli` / `aclnnInplaceBernoulli` 的公共签名和两阶段执行方式。 | ||
| 534 | +- `self/out` 的 dtype、shape、format 和非连续 view 语义保持不变。 | ||
| 535 | +- DSA 的 seed、offset 和 `1-prob` 传参方式与原实现一致。 | ||
| 536 | +- `prob=0/1` 继续使用原有精确快路径。 | ||
| 537 | +- FP64 bit-view 仅改变搬运解释,不改变输出数值。 | ||
| 538 | +- 非目标架构继续沿用原 `StatelessBernoulli` 路径。 | ||
| 539 | +- 若特定平台或 dtype 的融合路径出现兼容性问题,可在 Host 侧回退到原链路; | ||
| 540 | + 回退后需重新评估内存指标。 | ||