ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

PyPTO-Pro 多阶段 Kernel 数值误差定位实战手册:从错误统计量到精确替换分解

PyPTO-Pro 多阶段 Kernel 数值误差定位实战手册:从错误统计量到精确替换分解 PyPTO-Pro 多阶段 Kernel 数值误差定位实战手册从错误统计量到精确替换分解【免费下载链接】pypto-gymPyPTO-Gym 是基于 PyPTO 编程框架构建的算子与模型样例仓库项目地址: https://gitcode.com/cann/pypto-gym本指南围绕 CANN / pypto-gym 仓库中pypto-pro-op-kb知识库的数值误差定位 Playbook 展开。当 kernel 结构正确、能够运行、多数用例通过但评分输出仍过不了精度门、且无法判断是哪个阶段造成时本文给出了一条完整的排查路径先验证精度门本身的真实性再按门所衡量的量去测量用精确替换把误差逐阶段分解最后在动手构建修复前先用基准自身的公式核算成本。读完本文你将掌握一套一次运行即可锁定错误阶段的定位方法以及避免被错误统计量、失效证伪和陈旧结论误导的判别纪律。0. 适用场景先判断是否真的需要这篇指南数值误差定位 Playbook 的适用前提非常具体——kernel结构上正确它能跑通大多数用例通过但评分输出graded output仍然跨不过精度门accuracy gate而你不知道是哪一阶段stage的错。它之所以被写进知识库是因为在一次分阶段多 matmul kernel 的排障中一个看起来显然的统计量两次把矛头指向了错误的阶段白白消耗了两个完整的构建—测量—回退循环而本文记录的方法在一次运行内就锁定了真正的目标阶段。这个背景本身就说明了主题的危险性多阶段 kernel 的数值误差不会自动指向真正的肇事阶段必须用受控的分解手段去逼问它。该 Playbook 在知识库中的路由入口是 ROUTER.md 中 Localise a numerical error 一行对应技能为pypto-pro-op-develop。1. 第 0 步动手前先确认精度门是真的一份失败的评测报告证据价值在于它证明了你运行的那个门而不是关于 kernel 本身。因此排查的第一步不是看 kernel而是审查门。这一步有两个检查都便宜而且都真实地制造过假失败。1.1 使用任务配置的比较器绝不静默地自己重写一个Playbook 记录了一个真实的教训一份手写的近似比较器曾在部分正常的 kernel上报告0/20 全错因为它一次性错在了四个地方flag 阈值用了10 × threshold还是threshold——写错成threshold会严格 10 倍bf16 小值边界写成了2**-11而那是fp16行bf16 行是2**-8抵消区cancel region规则整个缺失CPU 基线CPU baseline整个缺失。这四个错误叠加就会把一个本应部分通过的 kernel 判成全军覆没。完整的门模型见 constraints/precision.md 中门到底测量什么一节比较分两阶段进行——第一阶段整体MERE threshold且MARE 10 * threshold直接通过否则进入第二阶段把所有元素分进 normal / small-value / cancellation 三个区域分别判定三个区域必须全部通过。仓库里可以找到真实比较器的实现例如 tests/ops/utils/compare.py 与 src/pypto_gym/ops/pypto_tensor/common_utils/compare.py它们先对 NaN/Inf 做位置级检查NaN 位置必须完全一致否则直接判失败再按atol rtol * |ref|构造容差、统计超过容差的误差点数量并与max_error_ratio比例阈值比较。这也印证了 Playbook 的结论误差是按元素判定、按区域汇总的任何整个张量一个数的近似都可能南辕北辙。1.2 用 harness 的裁决passed而不是用汇总统计量MARE最大绝对相对误差是被最小的|golden|主导的 max 统计量因此它随真实精度的变化是非单调的在这次算子上一个严格更精确的方案测出了更差的 MARE。所以判断成败要看passed不要看 MARE 这种汇总数。只有当门本身可信之后一次失败才值得投入调查。这条纪律被知识库在 pypto-pro-framework-findings.md §21 中重申为硬性规则验证者必须使用任务显式配置的比较器并记录其来源与版本如果拿不到就大声失败fail loudly绝不能静默回退到本地近似实现。2. 第 1 步测量与门所测量的相同的量这是整篇 Playbook 最容易出错、也最常被违反的一步让统计量匹配正在失败的区域。统计量与判定区域错配是追错阶段最常见的原因。门约束的是什么你应该测量什么正常区域的相对误差相对误差近零输出小值区 / 抵消区的绝对界绝对误差2.1 案例相对统计量测了分布的身体失败却在尾巴在原案例中每一次失败都发生在小值区域——对抵消产生的近零输出施加的是绝对2**-16界而诊断脚本报告的是相对误差并用0.1 × 张量 RMS作为截断来防止抵消项主导统计量。这个截断对描述张量主体是合理的但对这个问题完全错误它测的是分布的主体body而失败活在尾部tail。结果它把肇事阶段报告为1.2× CPU 参考而真正要紧的阶段其实是 2.8 倍更差。2.2 报告百分位而不是单个数字请报告p50 / p99 / p99.9 / max等百分位而非单一数值。分布顶端的相对参考倍数才是修复必须买回来的因子。一个把尾部误差藏进均值的统计量会让你高估或低估修复收益。3. 第 2 步用精确替换做逐阶段分解仅在假设成立时使用正交叠加3.1 精确替换exact substitution对一条链A → B → C把每一阶段替换为它的精确fp64值重新运行。在选定与门匹配的统计量之前保留带符号的逐元素误差truth exact_C(exact_B) e_inherited exact_C(device_B) − truth e_own device_C(exact_B) − truth e_total device_C(device_B) − truth e_interaction e_total − e_inherited − e_own这些表达式要求device_C能直接接受exact_B而不产生额外的一次边界转换。如果它做不到就把那次转换当作另一个阶段来分析而不是静默地把exact_B强转之后把转换误差记到 C 头上。3.2 正交叠加只是诊断不是证明百分位、最大值和逐元素绝对误差都不满足正交叠加。只有当诊断使用 RMS、e_inherited与e_own近似零均值且不相关、e_interaction可忽略时下面的式子才是有用的自洽性检查rms(e_total)² ≈ rms(e_inherited)² rms(e_own)²这是在明确假设下的近似不是恒等式更不是分解正确的证明。如果相互作用项很大或误差相关正交检查即失效——此时应该去检查带符号项、在需要的地方补充定向替换而不是强行凑数。3.3 与 CPU 参考的同一分解对比把每个分量与 CPU 参考的同一分解对比。原保留运行报告了以下汇总值但没有保留原始误差数组和统计量名称因此3.51² 2.43² ≈ 4.27²这个数值关系只是历史背景不能作为可复用的证据新调查必须按上面的修正分解重新计算。贡献kernelCPU 参考历史解读从第一个投影继承inherited3.51e-61.24e-6报告为 2.8× 更差——这才是目标第二个投影自身的own2.43e-62.44e-6已达参考质量在保留的那次运行里这个对比支持不改第二个阶段。而没有分解时它看起来就是最明显的嫌疑犯——一个完整 cycle 被花在重写它上面。这组数字在 pypto-pro-framework-findings.md §24 中有更完整的背景同样是在一个分阶段多 matmul 链上对单个输出做绝对误差分解且给出了 4 累加器修复k % 4分桶 消费者端两两合并(p0p1) (p2p3)如何把继承误差从 3.51e-6 降到 1.68e-6、使整链与 CPU 参考对齐2.76e-6 vs 2.74e-6并且运行时不变、17/20 → 19/20。4. 第 3 步构建修复之前先给修复定价一个用吞吐换精度的修复可能反而降低它本想提高的分数。要先用基准自身的单位给两边都定价gain Σ_newly_passing (0.3 0.5·score_i) / N · 100 cost Σ_all_cases 0.5·Δscore_i / N · 1004.1 工作示例仅限于上面两条公式、不推广到更一般的情形让最后一个失败的 case 通过需要把一次 matmul 切到 cube 的 fp32 模式。这确实能赢回这一个 case但代价是每个case 大约 2 倍的运行时间。把两边代入gain和cost公式后众多小幅回归远远压过单点胜利因此正确的决定是带着这个失败的 case 发布并把这笔算术记录下来。4.2 不要把它读成定律那只是某一种加权下的算术不是关于逐 case 加权指标的普遍结论提高 pass 奖励、给 case 加不等权重、或者让回归变成亚线性符号就会翻转。真正可迁移的是流程——写下指标自己的公式、把两边代进去、再比较——而不是这个实例的答案。5. 第 4 步在重构任何已通过的东西之前先备份这一类 kernel 的每次重写都可能变成一次回退。先复制能工作的文件。在这个算子上尝试过的三次重构有两次被回退而备份是已通过状态存活下来的唯一原因。这条规则朴素但代价极高排在所有工程动作之前。6. 纪律这次调查翻车的三种方式Playbook 用三条反面记录总结出可复用的纪律每一条都对应一个具体的认知陷阱整张量统计量回答了与所问问题不同的问题。见第 1 步在从任何统计量得出结论之前先让统计量匹配失败区域。一次证伪过期了。一次实验显示某个候选修复毫无效果并正确地记录为已证伪——但它是在一个上游误差比现在大 1.5 倍、把效果淹没掉的条件下测的。上游阶段修复后同一个候选变成了剩余的主导项。负面结果是有效的但从它推出的结论却活过了它的前提条件。记录负面结果被测量时的条件并在主导它的东西发生变化时重新打开它。已证伪是关于一个配置的说法不是永久属性。用推理替代了测量。几轮误差建模产出了自信的预测约 2e-3 相对误差远低于阈值而设备实测推翻了它。模型并非无用——它们给候选者排了尺寸——但每一个真正要紧的决策都是由一次测量拍板的而两个没有测量就照做的预测都是错的。7. 离线敲定精度方案不需要加速器选择构建哪个方案不需要 NPU。把 kernel 的数据流在 torch 里重放一遍以 GM dtype 和操作数拆分深度为参数用真实的比较器评分。一次完整的方案对比——3 个问题尺寸 × 5 个候选——在一台没有 NPU 的笔记本上跑完并选出了最终能用的那个方案M1M128M512bf16 GM, 1 termFAILFAILFAILfp32 GM, 1 termFAILFAILFAILfp32 GM, 2-term splitPASSFAILFAILfp32 GM, 3-term splitPASSPASSPASS只有实现所选方案的 kernel 才需要硬件。这些方案的含义fp32 GM 中间量 bf16 残差项拆分、两 term 约 16 位尾数、三 term 约 24 位见 constraints/precision.mdpypto-pro-framework-findings.md §22 还补了一行fp32 GM fp32 matmulPASS/PASS/PASS并解释了机制长有符号和呈零均值高斯分布链上每次窄化贡献近似恒定的绝对误差落在[2**-8, 2**-3]附近的元素相对误差可达 4 以上且 0.1 的绝对误差会把元素推出抵消区、送进必须零超限的 normal 区——约每个 case 77 个元素全部 case 失败。同时它也强调只拆分需要拆的东西——本来就以 bf16 到达的权重残差项恒为零3-term 拆分错边是测出来和 2-term 完全相同的空操作。8. 证据实测环境与应用效果文中所有数字均基于Ascend A5与当时运行的比较器测得。该 Playbook 在两个分阶段 attention 类算子上应用后一个从几乎全错变成仅剩一个 case 不过另一个从从未跑通变成全部通过。逐阶段的机理fp32 链路与 phase 相关的条目按标题查、不按编号见 references/pypto-pro-framework-findings.md——该文件还记录了与本主题直接相关的两条框架发现§18 的 K 循环最后一个 matmul 必须用AccPhase.Final收口Partial贯穿甚至会让单 block 循环以device error type 0xFFFF崩掉症状与循环深度不成比例、根本不像累加 bug以及 §24 的深 K 链单累加器精度缺陷。这些是排查数值误差时最容易被误判为kernel 数值问题的相邻陷阱。9. 两个会说谎的代理指标以及各自的判别器在同一轮战役中两个代理指标从单一轴向读数出发而实际有两个轴都在动分别产出了自信但方向相反的错误诊断import_s看不到设备、驱动或编译器子进程的争用。一次启动测得 184 s同元组基准 24 s因import_s从 6.5 s 涨到 36.1 s 而被归为环境噪声之后一次运行import_s回到 4.9 s、启动反而更差478 s又被归为几何geometry导致。两次都是对同一代理的过度解读。判别器在同一台机器、同一组坐标上重跑同样的几何并紧挨着跑一次基线臂——这会把这慢吗变成是我的改动造成的吗。答案是 15.47 s 对 15.94 s什么都不慢什么都没引入。一个结果与旧结果在两个轴上不同关于任一轴都不说明任何事。一次构建在一台从未跑过的机器上丢了 20 个性能测量中的 11 个损失被归咎于该构建而同一字节级相同的归档在另一台机器上测出正常的 20/20。判别器在做任何工程之前先买那个只变一个轴的控制实验。它花了一个积分却省下了一次 diff 加一次板端会话。一般形式诊断之前先数一数有多少东西变了。如果变了不止一个第一步是做一个只改变其中一个的控制而不是先假设哪一个重要。10. 内部对照优于外部阈值修复数值缺陷时找到那个本不该动的叶子并证明它没动。修复一个 RMS 倒数把c_kv改善了 43×、query改善了 5.7×而k_rope——路径上没有任何倒数的唯一输出——在每种几何下都与参考逐位一致。这个未动的叶子比任何对被移动叶子的容差检查都更强地证明这次编辑没有越界。而一个通过的阈值可能是运气而非精度。某几何的mare从通过的 0.055 恶化到失败的 0.19同时它的mere改善了 16.6×。该几何处 fp32 主机 golden 停在 0.164在两个臂上都过不了同一个阈值——所以最初的通过是算术从未挣来的余量。读阈值必须紧挨着同精度主机对照来读绝不单独读。11. 与仓库实物的对照比较器长什么样为了让用配置的比较器可落地这里给出仓库中两个真实比较器的一致要点作为实现事实详见 tests/ops/utils/compare.py 与 src/pypto_gym/ops/pypto_tensor/common_utils/compare.py非有限值先于一切误差算术被检查NaN 位置必须完全匹配否则整 case 判失败单侧 Inf 会被饱和到 dtype 最大值后继续比较同号双 Inf 视为匹配并从统计中排除——这正好对应 precision.md 中NaN 位置必须精确匹配的门规则容差是逐元素构造的tolerance atol rtol * |ref|超限位置才计入误差点误差点数量再与max_error_ratio × numel的阈值比较——误差是按点计数、按比例放行而不是一个全局均值打印分布而非单点打印前若干个误差点的位置/值/误差/允许阈值以及最大误差点。这正是 Playbook 第 0 步和第 1 步的落地形态判定逻辑是逐元素、分区域的因此排查统计量也必须与之一致。如果你所在的任务没有给出这样的比较器实现请以 constraints/precision.md 的三区域模型为权威而不是自己发明一个。总结一次排查的完整检查单门是真的吗用任务配置的比较器参照 tests/ops/utils/compare.py 的实现语义用passed判定不用 MARE测对量了吗失败在小值/抵消区就用绝对误差并报告 p50/p99/p99.9/max分解了吗用 fp64 精确替换逐阶段计算e_inherited / e_own / e_total / e_interaction与 CPU 参考的同一分解对比定价了吗把指标公式两边的 gain 与 cost 都写下来再决定是否构建备份了吗任何对已通过代码的重构前先复制证伪过期了吗记录负面结果的测量条件上游变化后重新打开离线能定吗精度方案先用 torch 重放 真实比较器在 CPU 上敲定变了几根轴诊断前先数清变化轴数用单轴控制实验定责内部对照呢找本不该动的叶子证明它没动阈值永远与同精度主机对照并读。这套流程把多阶段 kernel 数值误差归属从猜测与反复试错变成了一次可复现、可审计、可离线预演的受控实验。【免费下载链接】pypto-gymPyPTO-Gym 是基于 PyPTO 编程框架构建的算子与模型样例仓库项目地址: https://gitcode.com/cann/pypto-gym创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表