:故障诊断与性能工程——掉卡、精度漂移与 ns/day 瓶颈定位)
分子模拟异构算力适配开发教程19故障诊断与性能工程——掉卡、精度漂移与 ns/day 瓶颈定位版本声明块工具/软件GROMACS 2026.x环境变量/性能指标体系OpenMMReference 平台参照语言/环境Linux、Python 3.10诊断脚本本文目标读完你面对“跑挂了/数值不对/太慢了”三类问题时都有一套定位流程而不是盲目重跑一句话结论异构 MD 的三类故障各有标准武器——掉卡类先看设备状态与健康流device plugin 的 ListAndWatch再谈重跑数值类用同种子同精度逐帧对账OpenMM Reference 平台是黄金参照跨引擎对账容差先声明再跑性能类靠GMX_DETAILED_PERF_STATS六指标定位到 PME 不平衡gmx tune_pme或 SIMD 误选GPU 构建配 AVX512 的经典坑官方建议 AVX2再动手。〇、本篇要解决的认知问题GPU 掉卡/ECC 错误/设备丢失从哪一层开始查重跑的代价怎么控制“数值不对”怎么定义、怎么对账跨引擎GROMACS vs OpenMM能对到什么程度性能问题的六指标证据链怎么读PME 不平衡与 SIMD 误选两个经典瓶颈怎么确认怎么把三类诊断固化成可复用的脚本与决策树一、机制解析1.1 故障分类学先分类再动手为什么这一节对你重要异构平台上“作业失败”的原因谱比单机宽得多调度层分配、容器可见性、驱动/ECC、引擎后端、物理参数五层都可能背锅不分类就动手的结果是“重跑一次碰运气”——长作业场景这是数小时的赌博。类别典型现象证据层第一步环境类掉卡/设备丢失CUDA error、设备初始化失败、Pod 里看不到卡设备状态、调度日志查设备健康不查物理数值类精度漂移能量异常、与已知结果偏差、两个引擎结果不同逐帧对账对账脚本不看速度性能类慢ns/day 低于预期/历史md.log 六指标指标归因不盲目换硬件分类的第一收益环境类问题重跑大概率复发卡真的坏了/可见性真的错了先修环境数值类问题重跑毫无意义确定性模拟重跑结果一样非确定性根源要靠对账找性能类问题重跑只是重新采样要看趋势。1.2 环境类掉卡的三层排查层 1——设备本体。掉卡最常见的物理根因是 ECC 错误与过热降频NVIDIA 用nvidia-smi -q看 ECC 计数与温度AMD ROCm 用rocm-smi昇腾npu-smi info。ECC 不可恢复错误DBE累积到阈值会让设备离线——这是“跑着跑着消失”的头号原因。层 2——调度可见性。设备在但作业看不见Slurm 的 job step 环境丢失第 16 篇问题 2、K8s 的 device plugin ListAndWatch 把设备标 Unhealthy第 14 篇——掉卡秒级上报靠它、容器未挂设备文件。症状一样应用报无设备层不同修法完全不同。层 3——引擎/运行时。设备可见但初始化失败驱动与 CUDA 工具链版本错位第 16 篇问题 3 的容器场景、后端构建不支持该架构第 2 篇 CMAKE_CUDA_ARCHITECTURES 编译期架构不匹配——no kernel image 错误。处置纪律长作业必须带 checkpointgmx 的 -cpo/-cpi 续跑语义——掉卡修复后从检查点续而不是从头第 17 篇调度器的断点续跑靠它作业脚本自检段第 16 篇打印可见性是层 2/层 3 的第一手证据。1.3 数值类对账的方法论对账reconciliation的定义同一物理体系、同一种子、同精度设置在两个或多个环境各自跑逐步/逐帧比较关键量——目的是回答“差异在哪个量级、来自哪一层”。三个层级成本递增、结论递强L1 能量对账比对平衡后势能均值——快但粗糙涨落掩盖小差异判定用相对偏差阈值如 0.1%阈值必须在跑之前声明——铁律“容差先声明再跑”继承自第 2 篇。L2 轨迹对账逐步比对坐标/力——位置漂移是混沌系统对初始误差的指数放大Lyapunov 不稳定性跨引擎的逐步坐标吻合在数学上不可能浮点结合序不同即发散——这是对账最重要的认知跨引擎看统计等价RMSD 分布、能量分布、扩散系数同引擎同构建看逐帧浮点确定性。L3 黄金参照OpenMM 的Reference 平台双精度确定性实现第 4 篇跑短程几百步作黄金值——任何新后端/新构建先用它校准小体系上 Reference 可接受地慢。跨引擎对账的合法容差来源mixed 精度的浮点噪声量级单精度 ~1e-7 相对误差累积、不同积分器实现的合法差异同为 Langevin 但离散化不同——OpenMM 8.2 起 LangevinMiddle 的 middle 离散化——期望“逐位一致”本身就是错误的验收标准统计等价才是。1.4 性能类六指标与两个经典瓶颈md.log 的性能指标体系第 12 篇铺过完整版ns/day、hour/ns、ms/step、Matom*steps/s、Mnbf/s非键吞吐、MFlops——后两者需GMX_DETAILED_PERF_STATS1。归因逻辑PME 不平衡经典瓶颈 1PME rank 过载时 PP rank 空等——日志的 PME/PP 计时分离、Matom*steps/s与Mnbf/s的剪刀差是证据。解法-npme调整或 cut-off/PME 网格再平衡gmx tune_pme自动扫描官方工具第 3 篇预告。SIMD 误选经典瓶颈 2官方性能页明示GPU 构建配 AVX512 的 CPU——官方建议“GPU 运行时 CPU SIMD 优先 AVX2 而非 AVX512”降频反噬gmx --version的 SIMD 行是证据重编译第 2 篇流程改 GMX_SIMD。launch 开销主导小体系 ms/step 高但 Mnbf/s 低——CUDA Graphs 的场景第 13 篇nstlist 偶数。带宽/切分问题vGPU 或多进程共享卡的 ns/day 腰斩——铁律 9 的实测复核第 14/17 篇。诊断决策树的根节点永远是“和什么比”——没有基线历史档案/参考硬件的“慢”是无法定位的第 12 篇的 perf-archive.json 与第 16 篇的 perf-ledger.csv 在这里兑现价值。二、完整代码与逐行剖析一个“数值对账器”——L1/L2/L3 三层对账的完整实现诊断工具箱的核心件#!/usr/bin/env python3MD 数值对账器同种子同精度跨环境比对。 三层L1 能量统计对账跨引擎合法→ L2 逐帧坐标对账仅同引擎同构建合法 跨引擎会因混沌发散——脚本会拒绝并解释→ L3 Reference 黄金参照校准。 铁律容差先声明再跑所有阈值是参数不是魔法数。 from__future__importannotationsimportjsonimportsysfromdataclassesimportdataclassfrompathlibimportPathimportnumpyasnpdataclassclassTolerance:对账容差——跑之前声明结果与容差比较不反过来。energy_rel:float1e-3# 平衡势能均值相对偏差L1跨引擎frame_rmsd_nm:float0.05# 逐帧 RMSDL2同引擎同构建——纳米级drift_per_step_nm:float1e-4# 前若干步的漂移率L2 早期帧defload_energies(mdlog_or_csv:Path)-np.ndarray:从 md.log 的能量段或预导出 CSV 读势能序列解析按第 12 篇锚定法扩展。textmdlog_or_csv.read_text(errorsreplace)importre vals[float(m.group(1))forminre.finditer(r^\s*Potential\s[-0-9.eE]\s([-0-9.eE]),text,re.M)]ifnotvals:raiseValueError(未解析到势能序列——检查文件格式)returnnp.array(vals)defreconcile_L1(ea:np.ndarray,eb:np.ndarray,tol:Tolerance)-dict:L1 能量对账平衡段后 50%均值相对偏差。跨引擎合法。aea[len(ea)//2:].mean()# 弃前半弛豫取平衡段beb[len(eb)//2:].mean()relabs(a-b)/max(abs(a),abs(b))return{level:L1,mean_a:a,mean_b:b,rel_dev:rel,tolerance:tol.energy_rel,pass:reltol.energy_rel}defreconcile_L2(xa:np.ndarray,xb:np.ndarray,same_build:bool,tol:Tolerance)-dict:L2 逐帧对账。same_buildFalse跨引擎时执行前 50 帧漂移率检查后拒绝全量。ifnotsame_build:# 混沌系统的对数跨引擎逐帧吻合在数学上不可能浮点结合序差异指数放大。# 合法检查前 50 帧的漂移率短程内放大未充分长程必须转统计对账。nmin(50,len(xa),len(xb))driftnp.linalg.norm(xa[n-1]-xb[n-1])/nreturn{level:L2-cross-engine,drift_per_step_nm:drift,tolerance:tol.drift_per_step_nm,pass:drifttol.drift_per_step_nm,note:跨引擎只查短程漂移长程等价性请走 L1/统计对账}rmsdnp.sqrt(((xa-xb)**2).sum(axis-1).mean())return{level:L2-same-build,rmsd_nm:rmsd,tolerance:tol.frame_rmsd_nm,pass:rmsdtol.frame_rmsd_nm}defgolden_reference_check(candidate:np.ndarray,golden:np.ndarray,tol:Tolerance)-dict:L3 黄金参照候选新后端/新构建vs Reference 平台短程结果。nmin(len(candidate),len(golden))rmsdnp.sqrt(((candidate[:n]-golden[:n])**2).sum(axis-1).mean())return{level:L3-golden,frames:n,rmsd_nm:rmsd,tolerance:tol.frame_rmsd_nm,pass:rmsdtol.frame_rmsd_nm,note:Reference 双精度确定性——新后端验收的第一道数值关}defmain()-None:示例流程两份能量序列对账L1。iflen(sys.argv)3:sys.exit(用法: reconcile.py a.md.log b.md.log [--same-build])same--same-buildinsys.argv tolTolerance()ea,ebload_energies(Path(sys.argv[1])),load_energies(Path(sys.argv[2]))reportreconcile_L1(ea,eb,tol)print(json.dumps(report,ensure_asciiFalse,indent2))print(结论:,PASSifreport[pass]elseFAIL——差异超容差按 1.3 节层级继续先查精度声明再查参数最后查实现)if__name____main__:main()逐段剖析容差全部参数化Tolerance dataclass对账结论是“结果 vs 预声明的容差”不是“看着差不多”——这是把第 8 篇“容差先声明再跑”铁律数值回归篇在诊断场景的复用。L2 的跨引擎拒绝逻辑是本脚本的灵魂same_buildFalse时不做全量逐帧比较而是短程漂移率 明确的 note 指路——承认混沌系统的数学事实并给出合法替代L1/统计比硬比 RMSD 得出“引擎有 bug”的错误结论负责任得多。L3 用 Reference 当黄金参照的定位几百步的短程校准它慢百倍量级——新后端验收第 10/12 篇场景的第一道数值关性价比最高的正确性投资。三、常见报错与排查问题 1现象——作业跑了几小时后报 CUDA errorXid 错误字样消失/中止。根因按 1.2 节三层走——最常见是 ECC DBE 累积层 1nvidia-smi -q的 ECC 段看 Retired/AGP 内存页其次是过热降频连锁同看温度段层 2/3 的可能由“重启后能不能复现”区分能复现→配置类不复现→物理类倾向。解法确认物理后处置——ECC DBE 达阈值的卡走 RMA/隔离K8s 侧让 device plugin 的 Unhealthy 上报把卡摘出调度面第 14 篇作业侧从 checkpoint 续跑-cpi损失限于最后一检查点之后。问题 2现象——两个引擎跑“同一个体系”能量对不上差了千分之几。根因先别怀疑引擎——合法差异源清单mixed 精度的浮点噪声第 18 篇协商层的精度声明一致吗、积分器离散化不同Langevin 的各实现差异、力场参数文件的加载路径差同 xml/top 差一个版本、以及根本不是同一个体系水模型/截止/耦合参数的建模差异。解法按 1.3 节层级收敛——先 L1 统计对账千分之几在 mixed 精度的合法容差内就收工超容差再下钻参数核对把“体系定义一致”的证据力场文件哈希、参数 dump进对账报告。问题 3现象——ns/day 比同型号 GPU 的历史档案低 30%。根因证据链定位——GMX_DETAILED_PERF_STATS1重跑拿六指标PME/PP 剪刀差大 → PME 不平衡tune_pmeMnbf/s 正常但 ms/step 高 → launch 开销小体系CUDA Graphs都正常 → 层 2 环境同节点共租、降频nvidia-smi -q -d PERFORMANCE看时钟别忘了 SIMD 行AVX512 坑。解法按瓶颈归因动刀——npme/tune_pme、Graphs 开启nstlist 偶数、换节点/时段、重编译 GMX_SIMDAVX2_256——每次只改一个变量并重测第 13 篇矩阵法的单变量版。问题 4现象——对账脚本的 L2 逐帧 RMSD 随帧数指数增长同引擎。根因同引擎同构建逐帧应该确定性吻合浮点结合序一致——指数发散说明不是数值噪声而是输入或构建有差异种子其实不同、tpr 不同版本 grompp 产物、或“同引擎”其实是不同构建精度/SIMD/后端不同的两个 gmx。解法比对双方的环境快照与构建三要素第 18 篇 JobResult.raw 的用途确认 tpr 哈希一致构建一致后 L2 才有意义——否则退回 L1 统计对账。四、动手练习练习 1基础任取两个能量序列或自己造两组带 5% 噪声的数据跑对账器 L1再用Tolerance(energy_rel1e-6)极限容差复跑观察 FAIL。判定成功标准两次运行的 pass 结论相反能解释“容差声明在先”为什么是对账的纪律而不是调容差迁就结果。练习 2进阶给对账器加统计等价检查两组能量分布的均值差与标准差比|μa-μb|/σ阈值 0.5——跨引擎的合法替代指标。判定成功标准新指标输出并与 L1 结论并存能说明为什么统计等价分布层面比逐点吻合帧层面是跨引擎的正确标准混沌发散的数学理由。练习 3思考题无标准答案如果为平台第 20 篇设计“自动对账”巡检——每晚抽 1 个体系跑三方GROMACS/OpenMM/Reference短程对账报警线怎么定思考方向验证要点① 三方的两两对账该用哪层L1/L2/L3② 报警的误报成本与漏报成本怎么平衡对账阈值不是越严越好③ 巡检结果怎么进第 12 篇的档案体系历史趋势 vs 单点报警。五、小结与下一篇预告本篇建起了诊断体系故障先分类环境/数值/性能——环境类查三层设备 ECC→调度可见性→引擎运行时不急着重跑长作业靠 checkpoint 保损失下限数值类按三层对账L1 能量统计跨引擎合法、L2 逐帧只对同构建、Reference 是 L3 黄金参照混沌发散让“跨引擎逐位一致”成为伪标准统计等价才是性能类靠六指标归因PME 不平衡tune_pme与 AVX512 坑改回 AVX2是两个经典确认点。对账器的容差先声明、跨引擎拒绝逐帧——把纪律写进代码。下一篇是全系列终章把适配层18、调度器17、基准流水线12、对账器19与 K8s/Slurm 双底座14-16组装成完整的异构算力 MD 平台——架构图、能力矩阵落地、断点续跑与可观测性19 篇知识的总装。本篇认知问题回显FAQQ1GPU 作业中途报 CUDA error 消失第一步做什么A先分层排查不急重跑层 1 设备本体nvidia-smi -q 看 ECC 不可恢复错误与温度——DBE 累积是掉卡头号原因层 2 调度可见性Slurm job step 环境注入、K8s device plugin 的 Unhealthy 上报层 3 引擎运行时驱动与工具链版本、编译期架构不匹配。确认物理故障后作业从 checkpoint 续跑gmx -cpi控制损失。Q2GROMACS 和 OpenMM 跑同一体系结果能逐帧一致吗A不能——混沌系统对初始误差指数放大Lyapunov 不稳定跨引擎浮点结合序不同必然逐步发散逐帧吻合在数学上不可能跨引擎的正确验收是统计等价平衡能量分布、RMSD 分布、扩散系数等逐帧对账只对同引擎同构建有意义浮点确定性OpenMM Reference 平台双精度确定性可作短程黄金参照。Q3ns/day 明显偏低怎么定位瓶颈A设 GMX_DETAILED_PERF_STATS1 重跑拿六指标ns/day、hour/ns、ms/step、Matom*steps/s、Mnbf/s、MFlops归因PME/PP 计时剪刀差 → PME 不平衡调 -npme 或 gmx tune_pme 自动扫描Mnbf/s 正常但 ms/step 高 → 内核 launch 开销小体系开 GMX_CUDA_GRAPHnstlist 取偶数CPU SIMD 行显示 AVX512 → 重编译改 AVX2GPU 运行时官方建议再查环境同节点共租、降频时钟。Q4数值对账的容差怎么定A容差必须在跑之前声明不是看结果再调mixed 精度浮点噪声量级单精度约 1e-7 相对误差决定 L1 能量统计对账的合法容差如千分量级积分器离散化差异是合法差异源要计入预期L2 同构建逐帧 RMSD 容差取数值噪声级如纳米级以下超出容差的差异按层级下钻精度声明→参数文件→力场版本→实现。