十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

PyPTO-Gym A5 Roofline 工作流与实测调优杠杆:从平台常量推导到带宽天花板

PyPTO-Gym A5 Roofline 工作流与实测调优杠杆:从平台常量推导到带宽天花板 PyPTO-Gym A5 Roofline 工作流与实测调优杠杆从平台常量推导到带宽天花板【免费下载链接】pypto-gymPyPTO-Gym 是基于 PyPTO 编程框架构建的算子与模型样例仓库项目地址: https://gitcode.com/cann/pypto-gymPyPTO-Gym 中面向 A5Ascend 950 家族NpuArch3510算子的性能调优参考指南围绕可复算的 roofline 模型 实测杠杆两条主线展开先讲如何在确认 A5 目标后从安装版本对应的平台 ini 推导 cube/HBM/UB 等常量并建立符号化 roofline再给出经设备实测排序的七个调优杠杆、A5 原语代价表、逐寄存器掩码成本与结构性杠杆最后给出基于数据证据的停止纪律。读完本文你将掌握一套从证据门禁、平台常量推导、profiler 瓶颈判定到杠杆落地与收尾的完整 A5 调优闭环可直接复用到 PyPTO-Gym 中任意 A5 算子如 BF16 operand-reuse 样例 这类 matmul 或 attention 族算子的性能分析与优化。一、适用边界仅在确认 A5 目标后加载本工作流A5 roofline 工作流是目标专属的参考页不允许把其中的常量或调优规则应用到未知或非 A5 平台。加载本工作流前必须先确认目标设备满足以下任一信号raw 输出3510NpuArch值helper 输出dav-3510runtime 输出DAV_3510构建目标dav-c310在 PyPTO-Gym 的调优 skill 中正式采集前会先执行环境探测例如 get_npu_arch.py 或读取构建配置记录设备型号、NpuArch、CANN/PyPTO 版本与pypto_pro.__file__仅当结果确认上述 A5 信号时才加载本文。对未知平台或非 A5 平台直接使用该平台的官方资料与本次 profiler 数据不套用 A5 的核数、容量、带宽、频率或经验结论。二、证据门禁计算 roofline 之前的四项记录在计算任何 roofline 数值之前必须先完成证据门禁Evidence gate否则数值估计视为未验证只能以 profiler 结果作为唯一调优依据记录检测到的设备型号与架构记录 CANN 与 PyPTO 版本以及解析得到的pypto_pro包路径从与该精确 runtime 一起安装的平台文件中读取常量保留用于每个实测结论的 profiler 输出。若任一输入不可得就把数值估计标记为 unverified仅用 profiler 结果指导调优。三、主证据源路径从安装树解析不跨 checkout 复制roofline 常量必须从已记录版本的安装树中解析严禁从另一个 checkout 复制数值。主证据源路径包括framework/src/platform/parser/simulation_platform/platform_config/950DT_957x.ini与检测 SKU 匹配的950DT_958x.ini、950PR_957x.ini或950PR_958x.iniframework/src/platform/parser/platforminfo.inipython/pypto_pro/runtime/compile_config.pypython/pypto_pro/runtime/platform.py这些文件只对匹配的安装版本构成一手证据。若路径或键名不一致应在安装源码中搜索并记录替换项而不要推测数值。四、推导而非转写从平台 ini 算术出 roofline本工作流刻意采用推导而不是转写页面上不保留任何独立于安装版本的常量所有数值都从随 runtime 安装的平台 ini 中读出pypto root/framework/src/platform/parser/simulation_platform/platform_config/SKU.iniSKU必须从检测到的设备解析不能假设读取哪个 ini 也要随数字一起记录。推导刻意表述为对 ini 的算术运算而非委托给工具因为仅凭本仓库即可复现是这部分必须保持的性质。所用公式如下cube FLOP/s M*N*K来自 [DtypeMKN]* 2 * cube_core_cnt * cube_freq HBM B/s cube_core_cnt * [AICoreMemoryRates]ddr_rate * cube_freq vector_core_cnt * [VectorCoreMemoryRates]ddr_rate * vec_freq estimate max(bytes / HBM, MACs*2 / cube FLOP/s)注意该模型是算术地板它只给搬运定价低于任何同时给 epilogue 中 vector 工作、权重流式而非峰值带宽、或先于内存饱和的 cube bound 定价的模型。因此必须先确定哪个资源是主 bound再针对模型优化且要逐 case 重算——同一个 kernel 在不同 shape 下主 bound 资源会变化单算子内部的 spread 可能与算子之间的 spread 一样宽。五、刻意选择 SKU四个 ini 之间差一个因子四个 A5 ini 共享NpuArch3510、cube_freq1650以及相同的 L2/UB/L1/L0 容量但核数不同且ddr_rate相差超过 2 倍。对错误的 SKU 计算 roofline结果就错这个因子。关键约束相同核数的950DT与950PR不能互换platform.py只报告DAV_3510加核数这把范围收窄到两个 SKU 而非唯一确定因此必须记录实际使用了哪个 ini。这一点与 evidence-protocol.md 中的 A5 边界一致DAV_3510加核数不能唯一确定 SKU拿不到可验证的设备名/HAL 时数值 roofline 标记 unavailable。同时公式中的符号必须先归一化到 SI 单位如cube_freq1650MHz 是1.650e9 cycles/s在所选 ini/schema 未说明ddr_rate单位bytes/cycle/core、速率系数还是已归一化带宽之前不得代入带宽公式。六、校准测量实测比值而非平台常量校准部分记录的是带来源的实测比值因为前面的证据门禁要求如此。字节计数模型是地板不是预测。它只给流量定价不包含 epilogue 的 vector 工作、权重流式、或先于内存饱和的 cube bound。先确定哪个资源真正 bind再对模型优化且必须逐 case 重算——同一 kernel 在不同 shape 下主 bound 资源会改变单算子内部的 spread 可能与算子间一样宽。显式给因果工作定价否则模型可错到 2 倍。统计完整 attention 矩形的模型会高估因果掩码 kernel。对掩码j i (S_kv - S)保留比例为(S*(S_kv-S1) S*(S-1)/2) / (S*S_kv)——当S S_kv时约 0.5S S_kv时约 1.0。因此跳过掩码工作在方形 case 上是必须的在短 query case 上则无收益忽略掩码的模型误差约为该比例的倒数。可达峰值占比。A5 上实测对齐平面的 MTE2 读约达 1.7 TB/s一个调优过的 vector-only 访存受限归一化量化 kernel8192x8192 fp16401 us达到 1.17 TB/s作者称其已坐在内存屋顶上而同一 shape 的未调优 kernel 只有 0.69 TB/s。由此得到两点与谁写的 kernel 无关真实 kernel 能达到的屋顶远低于理论峰值要对实测天花板而非峰值做校准同一 shape 上 tuned/untuned 的差距就是奖池的大小这是投入一轮调优前最值得估算的数字。七、Vector-only 天花板结构性限制要先算后做如果每核ddr_rate的拆分是物理的那么只使用section_vector()的 kernel 最多只能达到 vector 核份额——在950PR上大约是聚合带宽的一半。对一个需要约 1.59 TB/s 才能达标的内存受限 case约 1.48 TB/s 的 vector-only 理论天花板让目标无论如何都达不到无论 kernel 多干净。因此投入 vector-only 设计前要把两个数字都算出来如果需求超过 vector 份额缺口是结构性的任何 kernel 侧工作都无法弥补。该结论应视为假设而非常量同一 ini 块中 AICore 的ddr_rate31旁边是ub_to_ddr_rate128VectorCore 是16旁边40单位并不自洽上述解读只是与实测聚合带宽一致的读法。用测量裁决做一次纯 DMA 拷贝相同字节vector-only 对比 cubevector只变这一项同一轮运行中加 control variant之后再围绕答案设计。八、符号化 roofline给假设排序不建立真实延迟使用从上述源码读出的版本与 SKU 专属数值cube_time ≈ total_MACs / detected_cube_throughput vector_time ≈ vector_work / detected_vector_throughput move_time ≈ bytes_per_path / detected_path_bandwidth estimate ≈ max(cube_time, vector_time, move_time)这个模型给假设排序但不建立真实延迟重新加载计数、启动开销、依赖、占用率与编译器调度都可能改变结果。它对应 evidence-protocol.md 中 Roofline 终态证据的第一步记录语义必需的有效计算量、分层必要搬运字节、arithmetic intensity、平台峰值计算/带宽及来源由模型先路由为计算候选或搬运候选再用 profiler 与受控 A/B 验证关键路径。九、测量闭环六步协议调优的每次改动都走同一个测量循环冻结一个通过的正确性测试用与后续变体相同的输入、launch 几何、warm-up 与 profiler 配置捕获baseline从保留的 profiler 产物读取主导实测管道——cube 侧看aic_mac_ratio对aic_mte2_ratiovector 侧看aiv_vec_ratio对aiv_mte2_ratio一次只改一个相关因子work 分布、tile shape、缓冲、片上驻留、累加结构或文档化 dtype重新运行正确性并再次 profile只有当实测目标指标改善且不违反数值契约时才保留改动。采集与字段解析分别依赖 msprof-guide.md标准采集七组--aic-metrics sample-basedaicore.db并输出带逐核负载均衡段的summary.txt、msprof-op-guide.md 与 csv_fields_reference.md。判定主 bound 时按优先级匹配MTE2 busy 80% 判 MTE2 BOUNDCUBE 80% 判 CUBE BOUND以此类推否则无 bound阈值只用于安排下一项实验不用于判定完成。十、A5 原语代价表每 64 lane 寄存器下表提供 A5 dataflow 决策所需的 target-specific 实测数量级仅在目标门禁确认后使用targetA5Ascend950PR_957956 vector core测得时间2026-07随 A5 实测批次适用范围仅该 SKU。换 SKU 后必须重新测量不能直接复用本表数值原语代价备注vf.gather约 20 ns跨 lanevf.scatter约 18 ns跨 laneUB 往返含必需的vf.mem_bar(VST_VLD)约 16 ns跨 lanevf.load_align/vf.store_align 1 ns不跨 lane算术本身约 0.3 ns不跨 lane三个跨 lane 原语彼此相差不到 25%——ISA 不提供寄存器级 lane shift所有 UB 中转替代品都交同样的税。由此得到两条推论无 bank 冲突的 gather ≠ 便宜的 gather。padding pitch 仍然必要冲突时再差 15 倍但消除冲突不会让它接近load_align跨 lane 与不跨 lane 相差 20–35 倍。一个内层循环里如果有 1 次 gather 2 次 scatter即使两种写法 op 数完全相同UB 寻址也会占到 83%、算术只占 17%证据一个连续扫描算子64 元素 13 op。按 evidence-protocol.md 的 A5 边界该代价表与页内所有 lever 收益、校准测量、可达带宽均属unverified_external_historical仓库内不含原始 profiler artifact/命令这些数值只能用于同 SKU 候选排序不能代替当前算子的 trace/A-B也不能直接写成当前算子的已验证结论。十一、按实际回报排序的七个实测杠杆以下七个杠杆来自两个 attention 族算子从正确但慢到带宽屋顶的调优过程每个都是从逐 kernel profile 中挑选而非猜测每个数字都是同 case 前后的设备实测。1. 删除 shape 不再需要的工作。把 token 数 padding 到整 M tile 需要前置 pad kernel 和后置 strip kernel——但仅在M不是TM的倍数时。把两次 launch 都守卫在M Mp上、让 cube 直接读写真实 tensor直接去掉最大 case 的24.5%。这是历史诊断证据交付时必须把等价 tail 处理折叠进一次 launch或上报 blocker。2. 按传输大小定 tile而不是按 tile 定传输。一个拷贝 kernel 搬 67 MB 只有121 GB/s屋顶近 1 TB/s纯粹因为其列 tile 是 512 元素——一个 1 KB 的 DMA。加宽到 40968 KB就是全部修复。列 tile 要从你想要的传输大小来选。3. 把内层维度折进任务索引。同一 kernel 在外层按行 stride内层循环列 tile。在M 1——decode shape也是任何 decode-heavy 集合的大头——只有一行于是一个核干完所有活31 个核闲置。改为按(row, column_tile)对 stride 即可body 不动。只要外层维度可能很小就把内层折进来。4. 每输出行一个 task 可能是纯描述符开销。一个 RoPE kernel 跑了M * N 65536个 task每个发 8 个 128 字节 DMA506 us占该 case 的 33%。把 64 行批量成一个[TRR, HALF]tile 每 task——算术相同、字节相同、一次 strided 传输替代 64 次——降到46 us。寄存器函数只需要变成对寄存器的循环行边界对 elementwise pass 无关紧要因为每行操作数在每个 tile 中处于相同偏移。5. 加宽 cube 的 N tile 以拉长 DMA run。在TN 64时B tile 的每行是 24576 宽权重中的一段 128 字节 runmatmul 跑在约 1 TB/sTN 128让 run 翻倍达到1.72 TB/s坐在屋顶上。宽度会约束哪些 kernel 能用它而且部分 N tile 不会 fault——它会静默破坏自己那份输出所以对宽 tile 不能整除的宽度要保留窄变体。6. 把复用操作数提出内层循环——但盯紧并行度。把(m_tile, kv_tile)拍平成一个 task index 会让 query tile 每 KV tile 重载一次2.1 GB 流量而 134 MB 足够。完全提出后立刻又坏了别的东西——只剩n_mt个 task而 decode shape 有S 1于是某 case 只有32 个核分 4 个 task反而更差16.7 → 37.9 us。可行形态是每 (M tile × KV tile组) 一个 task由 host 选n_g ceil(cores / n_mt)刚好够把核填满的组数操作数重读n_g次而非n_kt次。最终15.7 us。7. 更大的 M tile 减少权重重读如果 L0A 允许。K 操作数每个 M tile 重读一次。TM翻倍减半该次数但一个[64, 512]窄 query tile 是 64 KB——整个 L0A没给第二个操作数留空间。改为按块走 contraction 维度两个 256 宽块跨循环都驻留L1每次使用时 L1→L0A让TM 64放得下且 GM 流量保持每 task 一次。此处约值 10%——小于流量算术预测因为重读本来就大量 L2 驻留实际改善的是 L2 压力而非 DRAM 流量。知道何时停。在这些杠杆之后kernel 在 351 us 内搬了 604 MB1.72 TB/s、72 us 内搬 125 MB1.74 TB/s、139 us 内搬 234 MB1.68 TB/s对照权重流式访问模式约 1.6 TB/s 的屋顶。此时再快只能靠让 kernel 搬更少的字节而不是让 kernel 更快。说出来并停下而不是继续调。十二、保留样例的范围operand-reuse 只示范一种拓扑KB 的 BF16 operand-reuse 实现 演示了一种复用拓扑并内嵌正确性测试每个 A tile 经a_l1→a_l0a驻留在内层输出列循环中复用a_left仅重载 B tile。它不证明某算子是 cube-bound也不证明该拓扑在别的 shape 或目标上更快。使用前先 profile 当前 kernel按目标 shape 重测性能。十三、局部杠杆见顶后的结构性杠杆上述每个杠杆都保留算法——只是重排时间、去重或重布局已存在的工作。当它们在字节或占用率墙上见顶、而字节算术说流量仍可降时剩余动作改变的是存在哪些工作和流量。以下三个杠杆来自同一硅片上 attention 族工作的实测结构可迁移数字不可让循环携带的归约驻留片上。每步都把累加器或 running max/denominator往返 GM workspace 的归约在低算术强度下往往就是主导流量——少 query 行的 decode 形状 attention 是典型 case。让它驻留 UB或 L0C跨过循环只在契约边界碰一次 GM。前提目标 tile 下放得进片上预算——要检查真实余量因为 bring-up kernel 在宽临时量消失后往往留下大量空闲 UB。风险片上累加是归约/cast 顺序变更在新边界验证cube 重叠依赖 L0C slot 时优先 UB 驻留。让每个共享操作数跨核只读一次。每个核都重读同一 GM 区域时聚合读是operand_bytes × core_count。最便宜优先先测 L2 是否已吸收它——多核读相同地址往往命中 L2 而非 HBM墙可能远小于字节数暗示的再重 tile 让共享维度成为内层循环显式 broadcast/shared-load 方案放最后因为它把读墙换成同步墙。上述实测杠杆 6 就是本杠杆的实例包括失败模式完全 hoist 饿死了核group 形态修复。拆分归约维度以提高占用率flash-decoding 形态。并行维度很小时把长归约轴跨核拆成可合并的 partial——softmax 为 partial output、running max、running denominator——再在廉价 final merge 中合并。前提归约存在可合并 partial 形式且 merge 相对获得的占用率很小扫描 split 数量因为过度拆分会让 merge 主导。merge 本身是 cast 顺序变更——对合并结果对照 reference 验证。这些是更大的改动通常移动归约或 cast 顺序一次只应用一个先在新边界重验正确性再测量。十四、逐寄存器掩码是一等成本hoist 它可能就是全部收益该结论由一条 ablation 阶梯确立先做 load/store-only floor rung再逐个加回 compute stage同一锁窗口内 ABAB 配对control drift 控制在约 0.3% 以下。在任何目标上引用下列数字前都要用同样方式重新推导。pl.minvf.update_mask每个寄存器组花费 10.3–13.6 ns。对照本文原语表——算术约 0.3 ns、load_align/store_align不到 1 ns——这意味着保护算术的掩码落在vf.gather的量级约 20 ns即是它保护的工作的 30–45 倍。每个寄存器组都重算谓词的循环付的是掩码的钱而不是计算的钱任何 buffering 或 blocking 都碰不到这个成本。拆分寄存器循环为全寄存器路径取 all-lanes 谓词加零或一次 trip 的 tail保留掩码在 floor rung 上的实测形态观察大而访存受限的 shape提升有限约 1.1 倍本就接近访存上限掩码不是主要成本中等 shape约 2 倍小而落在 L2 内的 shape约 3 倍掩码开销占比最高且不受访存上限压制比值反转是机制的自我证明vector-bound rung 变成了真正的 memory-bound。加速比不同是因为 8192 的 case 撞上 DDR 墙停下而较小的两个 L2 驻留——固定的每元素节省会因工作集落在 128 MiB L2 的哪一侧而呈现截然不同的比值。它是 value 等价的普通正确性套件即可覆盖全寄存器vf.update_mask(64)就是 all-lanes 谓词vf.select(v, ident, all)是恒等累加顺序不变tail 同时保留两者。这是 bit-exact 而非 within-tolerance——当输出正卡在阈值上时这点很重要。两个都是实测到的注意点。本页其他位置的 mask-hoisting 条目只报 5%8/16 列 tile 上还有 3–4% 的损失窄 tile 把 hoist 摊到 2–4 个寄存器上可能亏。短轴 case 要单独测而不是假设若结论不一致按宽度分发。此外零长 tail 是活跃危险vf.update_mask(0)到达零-trip tail body 内的vf.select/vf.reduce_*曾产生设备 fault 507035把 tail 范围钳到至少 1无害因为循环在那里恰好零-trip。关于读 floor rung 的两条推论load/store-only rung 不自动等于内存地板。先看它自己的 pipe 行上面的 rung 是aiv_vec_ratio0.658 对aiv_mte2_ratio0.337所以它是minimal-VF地板针对它取的每个比值都是对 vector 工作的比值。跨 DSL closure 让错误可见另一个 DSL 的完整kernel 在同一 shape 上击败了这个什么都不做的 rung而 hoisted rung 又击败了那个完整 kernel。stall 余量在 floor rung 里不在完整 kernel 里。实测 bubble1 - aiv_vec_time/aiv_time在 floor 是 34.2%在完整 kernel 只有0.8%随 stage 加入bubble 被吸收。floor 有 147 us stall所以更深的 buffering 能赢 147 us不成立——更深的 buffering 只在1 - aiv_vec_ratio在shippingkernel 中较大时才付钱。十五、Cube 核不能借来当 DMA 引擎在 PyPTO-Pro 26.0 上有两个相互独立的原因均实测或从安装源码读出L1 不能写回 GM。pypto_pro/ir/op/block_ops.py:233把store/store_tile的源限制为 Vec (UB) 或 Acc (L0C):465的move路径Mat-Left, Mat-Right, Acc-Vec, Vec-Vec也没给 L1 去 UB 的路。GM→L1 load 没问题:668所以唯一的 cube→GM 路径是 GM→L1→L0A/L0B→L0C→GM即穿过 matmul 累加器。文档页store.md:17把 L1/UB Tile 列为合法源安装代码不同意而跑的是代码。仅仅声明pl.section_cube()就在 vector 路径上付出 1.88 倍——launch 从 56 个 block 掉到 28 个同一 vector-only 工作上 803.5 us 对 427.2 us。在 store 限制生效之前cube assist 已经是净损失。同轮测试还实测到vector-bound kernel 上有大量空闲 DDR 带宽。同一 shape 的 read-only contention probe 多搬 28.6% 字节只多花 7.6% 时间——额外读以饱和率 26% 的边际 2.21 TB/s 被服务。所以这类算子族上vector-issue-bound 的结论不能再解释为带宽短缺。十六、何时停止用数据证明的墙停在一堵被数据证明的墙上搬运字节不可约减——每个读或写恰好一次、每个都喂给契约——并且占用率达到算法所暴露并行度的设备极限。记录证明它的测量。MTE2在 98% 单独不够MTE2在 98% 且它搬的每个字节都恰好读一次才够。按 SKILL.md 的调优主流程达到或未达到理想目标本身都不能提前结束或阻止交付数据墙只用于关闭受证据支配的候选全部来源与 final sweep 合法闭合后即交付同时保留反事实证据、如实报告阻断。十七、本页数字的来源与可复算性校准测量一节的模型不需要硬件即可复现从安装的平台 ini 重算即可。它是平台常量上的算术不是 profiler 输出应重算而非从此处引用。可达带宽数字是其他 A5 工作的引用实测保留它们是因为纯理论屋顶给不出能达多少比例的感觉它们是 scenario-specific 的——不要拿 1.17 TB/s 当另一个算子或 shape 的目标。任何新增的带宽或时长声明都需要带版本标记的 profiler artifact 与产生它的命令。完整采集、归档与主 bound 判定的实操命令见 msprof-guide.md标准/compare/quick/batch 四种模式、七组--aic-metrics、逐核负载均衡段与 bound 判定表证据与归档合同见 evidence-protocol.mddiscovery profile、case manifest、seed 契约、Roofline/流水终态证据三件套字段语义与阈值边界见 csv_fields_reference.md含 A5/CANN 9.2.0 上字节字段缺失与带宽替代方案的一手核实记录。【免费下载链接】pypto-gymPyPTO-Gym 是基于 PyPTO 编程框架构建的算子与模型样例仓库项目地址: https://gitcode.com/cann/pypto-gym创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表