ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

分子模拟异构算力适配开发教程(12):移植验证闭环——回归测试、ctest 与 ns/day 基准流水线

2026/9/10 20:58:55 拓冰建站 浏览量
分子模拟异构算力适配开发教程(12):移植验证闭环——回归测试、ctest 与 ns/day 基准流水线 分子模拟异构算力适配开发教程12移植验证闭环——回归测试、ctest 与 ns/day 基准流水线版本声明块工具/软件GROMACS 2026.x回归测试机制跨版本适用ctest/CMake基准体系 MPINATbenchMEM/benchPEP-h语言/环境Linux、Python 3.10解析流水线本文目标读完你能为任何移植后端搭起“三层验证 基准流水线”的完整闭环——这是铁律 8 的工程化落地一句话结论移植验证三层 单元测试make check/ctest无 GPU 时静默回退须用GMX_TEST_REQUIRED_NUMBER_OF_DEVICES强制→ 回归测试-DREGRESSIONTEST_DOWNLOADON或离线-DREGRESSIONTEST_PATH→ 实测基准MPINAT benchMEM/benchPEP-hmd.log 尾部 Performance 行自动化解析摩尔线程官方验证四步法Debug 构建 assert → 单测 → Release回归 → STMV/benchPEP-h 实测是这套闭环的工业实证。〇、本篇要解决的认知问题GROMACS 的测试体系分几层回归测试数据集怎么接入在线/离线GPU 相关测试有哪些专用环境变量“测试静默回退”为什么危险、怎么强制摩尔线程的验证四步法为什么要从 Debug 构建开始ns/day 基准流水线怎么搭md.log 的 Performance 段有哪些指标、怎么自动化解析一、机制解析1.1 测试体系的三层结构为什么这一节对你重要铁律 8 说“移植完成≠适配完成必须过测试再谈性能”——本篇就是这句话的操作手册。国产后端交付时最常见的验收纠纷“跑通了”vs“跑对了”全部源于跳层。层内容触发方式单元测试各模块 GTest 套件GPU 相关在src/gromacs/gpu_utils/tests/device_buffer、device_stream_manager、devicetransfers、gpu_aware_mpi、hostallocator、pinnedmemorychecker 等make check/ctest回归测试端到端模拟与参考值比对数据集独立仓库 gitlab.com/gromacs/regressiontests-DREGRESSIONTEST_DOWNLOADON配置期自动下载或-DREGRESSIONTEST_PATH路径离线实测基准真实体系的 ns/daybenchMEM ~82k 原子、benchPEP-h 12M 原子、STMV手动/流水线本篇 1.4回归测试数据集的下载 URL 记录在 GROMACS 仓库的tests/CMakeLists.txt里——离线环境多数国产超算无外网的正确姿势在外网机预下载数据集拷贝到集群-DREGRESSIONTEST_PATH指过去。1.2 GPU 测试的三个关键环境变量官方环境变量页2026.2的三个移植期利器GMX_TEST_REQUIRED_NUMBER_OF_DEVICES默认 0——设为正整数强制测试套件要求至少 N 块可用 GPU。为什么重要默认 0 时无 GPU 环境会静默回退 CPU——测试“绿了”但 GPU 路径根本没执行。移植验收必须设 1让“GPU 路径没跑”变成显式失败而非绿灯假象。GMX_EMULATE_GPU——CPU 参考实现模拟 GPU 路径调试用没有国产卡的 CI 机器上也能跑通 GPU 代码路径的逻辑查空指针/接口误用这类结构性 bug数值正确性另说。GMX_GPU_DISABLE_COMPATIBILITY_CHECK——绕过 OpenCL/SYCL 的硬件兼容性检查官方原话 “allows testing the OpenCL/SYCL kernels on non-supported platforms without source code modification”——这就是为移植新硬件准备的开关国产卡常不在兼容列表里开着检查会被拒之门外。测试运行的标准命令make tests -j N make check构建并跑全部ctest -N列举ctest -R test_name --verbose单个跑-R 支持正则过滤——GTest 的--gtest_filter也适用于测试二进制。1.3 摩尔线程四步法为什么 Debug 构建打底第 9 篇预告的官方验证路线摩尔线程 MUSA 后端的实际验证顺序① Debug 构建assert 生效 ↓ ② 单元测试ctest ↓ ③ Release 构建 回归测试 ↓ ④ STMV/benchPEP-h 实测基准①为什么用 Debug 打底Release 的-DNDEBUG会剥掉 assert——移植期最容易犯的“不变量被破坏”类错误如第 9 篇 warp 断言、buffer 尺寸断言在 Release 下静默滑过产出错的结果或晚期崩溃Debug 构建让这些问题在第一时间、第一现场爆出来。①②查结构性 bug③查数值正确性回归测试比对参考值④查性能——四步各管一层不可跳。这套方法论与 GROMACS 官方的“make check 回归”组合完全兼容——厂商实践与上游体系的交集就是标准答案。1.4 基准流水线从 md.log 到性能档案md.log 尾部的 Performance 段官方格式AWS 官方脚本佐证(ns/day) (hour/ns) Performance: 144.741 0.166 Wall t (s): 59.668完整指标体系六项ns/day、hour/ns、ms/step、Matom*steps/s、Mnbf/s、MFlops——后两项只在设置GMX_DETAILED_PERF_STATS时打印。计时控制GMX_DISABLE_GPU_TIMING/GMX_ENABLE_GPU_TIMING。基准体系的事实核对调研底账纠错benchMEM/benchPEP/benchPEP-h 的权威来源是MPINATGrubmüller 组https://www.mpinat.mpg.de/grubmueller/bench——注意官方名是 benchPEP-h不是 benchPEHSTMV 在 Zenodorecord 3893789www.gromacs.org/AboutGromacs/Benchmarks是 404不要引用。基准跑法三件套参数-resethway丢弃前半程计时排预热注意拼写不是 -resetheway、-noconfout、-pin on。二、完整代码与逐行剖析一条完整的基准流水线下载 benchMEM → 跑基准 → 解析 md.log → 生成性能档案JSON供第 17-20 篇的平台层消费#!/usr/bin/env python3GROMACS 基准流水线benchMEM 下载 → 多配置跑 → Performance 解析 → 档案输出。 铁律 6 的工程化每条性能记录都带硬件/体系/精度/参数上下文。 importjsonimportreimportsubprocessimportsysimporttimefrompathlibimportPath# MPINAT 权威基准入口benchMEM 单页提供 .tpr.gz 下载BENCH_MEM_URLhttps://www.mpinat.mpg.de/benchMEMdeffetch_benchmem(workdir:Path)-Path:下载 benchMEM 的 tpr页面提供 .tpr.gz实际文件名以页面为准。workdir.mkdir(parentsTrue,exist_okTrue)tprworkdir/benchMEM.tpriftpr.exists():returntpr gzworkdir/benchMEM.tpr.gzsubprocess.run([wget,-q,f{BENCH_MEM_URL}/benchMEM.tpr.gz,-O,str(gz)],checkTrue,timeout300)subprocess.run([gunzip,-kf,str(gz)],checkTrue)returntpr PERF_REre.compile(r^\s*\(ns/day\)\s\(hour/ns\)\s*\n# 表头行r^Performance:\s([0-9.])\s([0-9.])\s*\n# 数据行ns/day 与 hour/nsr(?:^Wall t \(s\):\s([0-9.])\s*\n)?,# Wall 时间可选行re.M)defparse_mdlog(mdlog:Path)-dict:解析 md.log 的 Performance 段六指标中常驻三项 可选详细项。textmdlog.read_text(errorsreplace)mPERF_RE.search(text)ifnotm:raiseValueError(f{mdlog}无 Performance 段作业异常先看该文件尾部)result{ns_per_day:float(m.group(1)),hour_per_ns:float(m.group(2))}ifm.group(3):result[wall_s]float(m.group(3))# 详细指标Mnbf/s、MFlops需 GMX_DETAILED_PERF_STATS1 才打印——有则收forkey,patin[(matom_steps_s,rMatom\*steps/s:\s([0-9.eE])),(mnbf_s,rMnbf/s:\s([0-9.eE])),(mflops,rMFlops:\s([0-9.eE])),(ms_per_step,r^\s*([0-9.])\sms/step)]:mmre.search(pat,text,re.M)ifmm:result[key]float(mm.group(1))returnresultdefrun_bench(tpr:Path,label:str,gmx_args:list[str],outdir:Path,repeats:int3)-dict:跑基准每配置重复 repeats 次取中位数摩尔线程官方方法论。 -resethway 丢前半程计时-noconfout 免结构输出-pin on 线程绑定。samples[]foriinrange(repeats):woutdir/f{label}-{i}w.mkdir(parentsTrue,exist_okTrue)cmd[gmx,mdrun,-s,str(tpr),-deffnm,str(w/md),-resethway,-noconfout,-pin,on,*gmx_args]rsubprocess.run(cmd,capture_outputTrue,textTrue,timeout7200)ifr.returncode!0:return{label:label,error:r.stderr.strip()[-200:]}samples.append(parse_mdlog(w/md.log)[ns_per_day])samples.sort()return{label:label,ns_per_day_median:round(samples[len(samples)//2],2),samples:[round(s,2)forsinsamples]}defmain()-None:outdirPath(bench-pipeline);outdir.mkdir(exist_okTrue)# 配置矩阵完整上下文记录铁律 6——正式档案还应补硬件/构建信息见下configs{gpu-offload:[-nb,gpu,-pme,gpu],gpu-resident:[-nb,gpu,-pme,gpu,-pmefft,gpu,-bonded,gpu,-update,gpu],}# 上下文采集gmx --version 是构建信息的权威来源版本/后端/精度versubprocess.run([gmx,--version],capture_outputTrue,textTrue,timeout30).stdout ctx{ln.split(:)[0].strip():ln.split(:,1)[1].strip()forlninver.splitlines()if:inln}tprfetch_benchmem(outdir/data)archive{timestamp:time.strftime(%Y-%m-%dT%H:%M:%S),system:benchMEM (~82k atoms, membrane protein, 2 fs),gmx_build:ctx,results:{}}forlabel,argsinconfigs.items():print(f跑{label}...)archive[results][label]run_bench(tpr,label,args,outdir)print(f -{archive[results][label]})outoutdir/perf-archive.jsonout.write_text(json.dumps(archive,ensure_asciiFalse,indent2))print(f档案落盘:{out})if__name____main__:main()逐段剖析PERF_RE的多行正则锚定“表头数据行”的完整结构而非只匹配Performance:一行——防误匹配正文里可能出现 “Performance” 字样的地方不止一处但这个三行结构是唯一的。这是第 3 篇单行解析的升级版。repeats3取中位直接引用摩尔线程官方方法论每体系测 3 次取中位、多次重复无波动——把厂商的验收规范变成代码默认值。-resethway的拼写不是 -resetheway与-noconfout、-pin on三件套来自 AWS 官方基准脚本的实践——基准参数的可信度同样要有出处。ctx采集 gmx --version 的全部键值对进档案版本/后端/精度跟着性能数字走——档案里每条 ns/day 都能回答“在什么上跑的”铁律 6 的完整形态。这份 JSON 在第 20 篇会被平台层的调度器直接消费。验证闭环的 Makefile 化把 1.3 四步法固化移植项目的 CI 骨架# Makefile.verify —— 移植验证四步法摩尔线程路线的 Makefile 化 # 用法: make verify-gpu全流程/ make step1-debug 等单步 GMX_SRC ? ./gromacs BUILD ? ./build PREFIX ? /opt/gromacs-verify step1-debug: # ① Debug 构建assert 生效——移植期第一道网 cmake -S $(GMX_SRC) -B $(BUILD)-dbg -DCMAKE_BUILD_TYPEDebug \ -DGMX_GPU$(BACKEND) -DREGRESSIONTEST_PATH$(REGPATH) cmake --build $(BUILD)-dbg -j$(shell nproc) step2-unit: step1-debug # ② 单元测试强制要求 GPU拒绝静默回退 GMX_TEST_REQUIRED_NUMBER_OF_DEVICES1 \ ctest --test-dir $(BUILD)-dbg --output-on-failure -R Gpu|gpu|Device|device step3-regression: # ③ Release 回归测试 cmake -S $(GMX_SRC) -B $(BUILD)-rel -DCMAKE_BUILD_TYPERelease \ -DGMX_GPU$(BACKEND) -DREGRESSIONTEST_PATH$(REGPATH) cmake --build $(BUILD)-rel -j$(shell nproc) \ ctest --test-dir $(BUILD)-rel --output-on-failure step4-bench: # ④ 实测基准benchMEM 流水线 python3 bench_pipeline.py verify-gpu: step2-unit step3-regression step4-bench echo 四步全绿移植验收通过三、常见报错与排查问题 1现象——移植后的后端make check全绿但实测结果能量/结构明显错误。根因测试静默回退——GMX_TEST_REQUIRED_NUMBER_OF_DEVICES默认 0无 GPU或 GPU 探测失败时 GPU 测试回退 CPU 路径“绿灯”测的是 CPU 而非你的后端。解法验收跑测试必设GMX_TEST_REQUIRED_NUMBER_OF_DEVICES1Makefile 已固化日志里逐条确认 GPU 测试实际执行了ctest --verbose 的输出含设备信息。问题 2现象——国产卡上跑回归测试配置阶段直接被拒unsupported device / compatibility 报错。根因OpenCL/SYCL 后端有硬件兼容性白名单检查新卡不在名单里——测试还没开始就被挡在门外。解法设GMX_GPU_DISABLE_COMPATIBILITY_CHECK官方为“在非支持平台测试内核”准备的开关注意这只解除门槛不保证正确性——回归测试的比对结果才是判据。问题 3现象——回归测试部分 case 失败错误集中在特定类型如 PME 相关。根因定位价值信息——回归测试按功能覆盖失败聚集的类别指向移植的薄弱模块PME 的 FFT 库适配第 2 篇的 GMX_GPU_FFT_LIBRARY 选择。解法ctest -R 失败测试名 --verbose单跑看详细差异GROMACS 回归测试报告参考值 vs 实测值按聚集类别回查该模块的后端实现第 5 篇的文件分派地图定位实现文件。问题 4现象——基准数字波动大同配置跑三次差异 5%不敢写进报告。根因预热不足-resethway 缺失时前半程含初始化开销、频率漂移卡的热设计功耗降频、或同节点有其他负载。解法三件套补齐-resethway/-noconfout/-pin on跑前确认卡空闲npu-smi/nvidia-smi/rocm-smi 按硬件选重复 ≥3 次取中位并把样本方差写进档案流水线已存 samples 数组——波动的数字要带着波动信息进档案而不是只留中位数。四、动手练习练习 1基础对任一 GROMACS 安装不必是移植版跑ctest -N若有构建树或用本篇 Makefile 的 step1/step2 走一遍记录 GPU 相关测试的数量与名称分布。判定成功标准产出测试清单如 device_buffer/device_stream_manager 等至少 5 个 GPU 相关测试名能说明哪些测试名暗示测的是 gpu_utils 的哪个抽象对照第 5 篇。练习 2进阶在无 GPU 的机器上分别以默认与GMX_TEST_REQUIRED_NUMBER_OF_DEVICES1跑同一组 GPU 测试对比行为差异。判定成功标准观察到默认时静默跳过/回退、强制时显式失败——两侧行为都有输出证据用自己的话解释为什么移植验收必须用强制模式。练习 3思考题无标准答案回归测试在“跨后端验证”里扮演什么角色它比单元测试多覆盖了什么思考方向验证要点① 单测验证模块不变量buffer 对不对回归验证端到端数值能量对不对——中间隔着哪些层② 回归参考值是怎么来的同一后端跑的参考能服众吗③ 国产后端的回归参考值应该用什么生成CUDA/NVIDIA 上游结果 vs 本后端 Debug 结果的取舍。五、小结与下一篇预告本篇把铁律 8 变成了可执行的闭环三层测试单测/回归/实测各管一层结构/数值/性能三个 GPU 测试环境变量里 REQUIRED_NUMBER_OF_DEVICES 拒绝静默回退、EMULATE_GPU 给无卡 CI、DISABLE_COMPATIBILITY_CHECK 为新硬件开门摩尔线程四步法Debug assert→单测→回归→实测是工业实证基准流水线把 md.log 六指标解析 三次取中 全上下文档案化——perf-archive.json 将成为第 20 篇平台调度器的输入。进阶篇9-12到此收官MUSA 全栈移植、openmm-musa 插件、昇腾算子路线、验证闭环——四篇构成“移植怎么做、做完怎么验”的完整故事。下一篇起进入高级篇13-16先讲源码级调优CUDA Graphs、GPU-aware MPI、NVSHMEM再转向算力池化K8s Device Plugin、Volcano、Slurm/Apptainer——从“单卡跑对”迈向“集群跑好”。本篇认知问题回显FAQQ1GROMACS 的回归测试数据集怎么接入离线环境怎么办A两种方式配置期-DREGRESSIONTEST_DOWNLOADON自动下载或离线环境预先下载后用-DREGRESSIONTEST_PATH路径指定数据集在 gitlab.com/gromacs/regressiontests 仓库下载 URL 记录在源码 tests/CMakeLists.txt 中。Q2为什么移植后跑测试必须设 GMX_TEST_REQUIRED_NUMBER_OF_DEVICESA该变量默认 0——无 GPU 环境下 GPU 测试会静默回退 CPU 路径测试全绿但 GPU 路径根本没执行设为 1 强制要求至少一块可用 GPU让“GPU 路径没跑”变成显式失败。配套的 GMX_EMULATE_GPU 可在无卡 CI 上模拟 GPU 路径查结构 bugGMX_GPU_DISABLE_COMPATIBILITY_CHECK 可绕过 OpenCL/SYCL 硬件白名单为新硬件测试准备。Q3benchMEM 基准体系从哪里下载正确名称是什么A权威来源是 MPINATGrubmüller 组基准集 https://www.mpinat.mpg.de/grubmueller/benchbenchMEM 约 8.2 万原子膜蛋白体系、benchPEP、benchPEP-h 各 1200 万原子注意官方名是 benchPEP-h 不是 benchPEHgromacs.org 的 Benchmarks 页面不存在404STMV 在 Zenodo record 3893789。Q4md.log 里能看到哪些性能指标怎么让自动化解析Amd.log 尾部 Performance 段常驻 ns/day、hour/ns、ms/step、Wall tMatom*steps/s、Mnbf/s、MFlops 需设 GMX_DETAILED_PERF_STATS1 才打印解析锚定表头行Performance: 行的多行结构正则捕获第一列 ns/day基准跑法配 -resethway丢弃前半程计时注意拼写、-noconfout、-pin on重复 3 次取中位。