Files
SystemSimulationApp/docs/other/求解器性能优化任务清单.md
T

45 KiB
Raw Blame History

求解器性能与鲁棒性优化任务清单

用途:记录求解器优化的现状、证据、实施顺序和验收结果,供后续开发前后对比与持续更新。 首次建立:2026-08-17 基线代码:6bb0591d320d0c448ee8d224dd44127bfe3ce00f(本地 model-development) 基线模型:tests/data/test_mql-full-branches-01-04.xml 模型 SHA-256:2fb95e65f5de0c85a6a17802aef74ea004087323fd00fd8d01acf0184ff71d48

1. 使用规则

本文档不是一次性的建议列表,而是优化工作的验收账本。

  • 状态统一使用:未开始、进行中、部分实现、已完成、阻塞、不采用。
  • 只有同时完成代码、自动测试、基准复测和本文档更新后,任务才可标记为“已完成”。
  • 每次性能对比必须记录代码提交、工作树状态、输入哈希、解释器与依赖版本、硬件和运行参数。
  • 正确性门槛先于速度收益。若结果越过误差契约,即使运行更快也不能合入默认路径。
  • 容差、模型方程或输出字段发生变化时,必须单独说明;不得将其伪装成纯性能优化。
  • 墙钟时间只在同一台机器、相同负载和相同环境下直接比较;跨环境以工作量计数和正确性指标为主。
  • 每项优化都应保留明确的关闭开关或旧路径,直到新路径经过复杂模型和通用回归验证。

2. 当前结论与基线

2.1 关于 2.05 s 卡死

当前随附 XML 的磁盘配置是 tStop=0.81 s,因此原文件本身不会运行到 2.05 s。将停止时间仅在内存中改为 2.10 s 后,当前代码已经完整越过 2.05 s 并正常结束:

  • 2.040432 s:墙钟 114.065 s
  • 2.046141 s:墙钟 120.746 s,期间 CPU 时间持续增长
  • 2.051691 s:墙钟 121.548 s
  • 2.100000 s:完成积分并进入后处理
  • 总运行完成,无重试、无非线性回退,也没有无进度死锁

因此,当前证据支持“此前的 2.05 s 卡死在现版本中没有复现”;该区间仍存在数秒级慢推进。10 s 尚未验证,不能由本次结果外推保证。

2.2 环境说明

仓库内 .venv 当前不完整,本次复测使用现有 /opt/srm-trial-review/.venv:

项目 本次值
Python 3.12.3
NumPy 2.4.6
SciPy 1.17.1
求解器 BDF
输出步长 0.01 s
执行路径 stream/cancel-check

该环境满足仓库依赖范围,但并非已经锁定的正式项目环境。当前物理解哈希与历史调研文档不同,所以逐位结果基线必须在正式锁定环境中再次确认。

2.3 当前实测基线

指标 原始 0.81 s 仅内存延长至 2.10 s
状态 完成 完成,越过 2.05 s
墙钟时间 63.779 s 126.211 s
积分时间 62.116 s 122.180 s
后处理时间 1.118 s 2.703 s
最大 RSS 165,464 KiB 198,348 KiB
输出样本数 82 213
状态数 74 74
nfev / njev / nlu 3763 / 253 / 761 6734 / 487 / 1507
接受步 1076 1857
分段启动 3 5
状态切换 0 2
重试 0 0
有限差分附加 RHS 估计 7843 15097
压力闭合次数 30,502 57,601
非线性/块/稠密回退 0 / 0 / 0 0 / 0 / 0
最大热流体外迭代 3 3
Jacobian 稀疏度 1284 nnz / 31 色 1284 nnz / 31 色

补充观察:

  • 积分占总耗时约 97%,当前首要瓶颈不是后处理。
  • 2.10 s 运行中,估计总 RHS 工作量约为 6734 + 15097 = 21831;有限差分扰动约占 69%。
  • 压力闭合约为每次估计 RHS 2.64 次,但全部走已播种的因果路径,没有触发 least_squares。
  • 全局因果执行已启用:快速执行 22,216 次,完整残差审计 351 次,审计失败 0 次,旧路径回退 0 次,审计间隔为 64。
  • 当前结果哈希仅作为本次环境的诊断记录:0.81 s 为 c6354c97...,2.10 s 为 efef49f8...;它们暂不作为跨环境验收标准。

2.4 当前模型结构基线

项目 数量
XML 组件 / 编译组件 99 / 98
连接 106
连续状态 74
代数未知量 / 方程 472 / 472
原始关联矩阵非零元 / 方程块 919 / 58
effort 未知量 / flow 未知量 272 / 200
effort 等价组 / 可消去重复 effort 68 / 204
显式 flow/force 赋值 200
stream 块 / stream 未知量 9 / 192
结果变量 1,021

3. 总体验收协议

每个优化 PR 至少执行以下分层验证;高风险改动不得只用单点输出或单个哈希判断正确性。

3.1 快速结构检查(CI)

  • 模型输入 SHA-256 与固定 fixture 一致。
  • 组件、连接、状态、代数方程和 stream 结构数量符合预期。
  • Jacobian 结构至少覆盖已知跨域依赖,并通过稠密数值扰动抽查。
  • 因果计划覆盖率、回退原因和审计失败数可观测。

3.2 数值检查点

至少覆盖以下区间和模式边界:

  • 0.68–0.71 s:历史慢区。
  • 0.79–0.81 s:原始模型终点及信号事件附近。
  • 2.00–2.10 s:此前报告卡死区间和状态切换。
  • 10 s:长时间模式变化验证,完成 OPT-09 后启用。

每个检查点比较:连续状态、关键压力/流量/位移/速度、事件时刻与顺序、模式状态、有限性、最大缩放残差及守恒量。

3.3 性能记录

每次正式对比至少预热 1 次、测量 3 次并报告中位数,同时保存:

  • 总时间、积分时间、后处理时间、CPU 利用率、峰值 RSS。
  • nfev、njev、nlu、接受/拒绝步、分段和重试次数。
  • SciPy 模式的有限差分 RHS 估计;callable 模式的真实扰动、基准和 Jv 审计 RHS 计数;Jacobian 颜色数与构建时间。
  • 代数闭合次数、快速因果次数、完整审计次数和各类回退次数。
  • stream/热流体迭代次数、物性缓存命中率、事件候选与定位次数。
  • 输出标量数、编码字节数、传输字节数和后处理峰值内存。

4. 优化任务总览

优先级定义:P0 为基线或正确性前置,P1 为主要性能收益,P2 为第二阶段,P3 为战略性或条件性工作。

ID 优先级 任务 当前状态 难度 预期价值 主要依赖
OPT-00 P0 固化复现、环境和回归基线 进行中 中 很高 无
OPT-01 P1 完成因果代数内核与坐标消元 部分实现 中高 中高 OPT-00
OPT-02 P1 建立扁平数值 IR 和数组执行内核 未开始 很高 很高 OPT-01
OPT-03 P1 稀疏 Jacobian 数值层与解析/半解析演进 部分实现 很高 很高 OPT-00;解析链可与 OPT-02 分阶段
OPT-04 P1 stream 拓扑传播与物性成组复用 部分实现 中高 中高 OPT-00
OPT-05 P1 状态缩放、分量容差和步长策略 未开始 中高 中高 OPT-00
OPT-06 P2 事件检测与 dense output 按需化 部分实现 中 中 OPT-00
OPT-07 P2 输出、后处理和传输内存优化 未开始 中 中高(长仿真) OPT-00
OPT-08 P2 进度、取消和服务并发鲁棒性 部分实现 中 中 OPT-00
OPT-09 P0/P2 建立 10 s 长时验证与模式覆盖 未开始 中高 很高 OPT-00
OPT-10 P3 明确高指数 DAE/强非光滑系统边界 未开始 很高 条件性 OPT-09

推荐实施顺序:OPT-00 → OPT-03/OPT-01 → OPT-04/OPT-05 → OPT-02 → OPT-06/OPT-07/OPT-08 → OPT-09。其中 OPT-02 与 OPT-03 可先做最小原型,再根据端到端数据调整顺序。

5. 详细任务

OPT-00 固化复现、环境和回归基线

目标:先让“是否更快、是否仍正确、是否又卡住”可以稳定复现和自动判断。

当前状态:已有手工 0.81 s 和 2.10 s 复测及若干结构回归;复杂 XML、正式运行环境、分层性能门槛尚未完整固化。

工作项:

  • 将复杂 XML 作为正式测试 fixture 纳入版本控制,并在测试中校验哈希。
  • 修复或重建项目 .venv,锁定 Python、NumPy、SciPy 及平台信息。
  • 将临时探针整理为仓库内可重复运行的 benchmark,不依赖 /tmp 文件。
  • 添加 0.81 s 和仅改 tStop=2.10 s 的标准运行入口。
  • 添加模型结构快照断言;结构有意变化时显式更新原因。
  • 定义 physical-state-v2:仅包含物理状态、关键代数量、事件与模式,不包含展示字段和易变诊断字段。
  • 将完整 API 输出哈希与物理解哈希分开,分别用于输出契约和数值回归。
  • 建立短 CI、夜间 0.81/2.10 s、定期 10 s 三层任务。
  • 保存机器可读的 JSON 基准结果,避免只在文档中抄写数字。

验收条件:

  • 干净环境一条命令可复现;失败时能区分超时、无进度、数值失败和服务失败。
  • 正式环境连续 3 次完成 2.10 s,结果满足数值契约且无非预期回退。
  • 性能报告完整记录环境、提交、工作树、输入哈希和统计口径。

前后对比:

指标 当前 完成后
正式锁定环境 无 待填
复杂模型自动回归 部分 待填
物理解哈希 环境相关 v1 待填
2.10 s 连续成功率 单次证据 待填

OPT-01 完成因果代数内核与坐标消元

目标:在已存在的因果快速路径上,真正移除运行时冗余坐标和对象访问,而不是再次实现一套同类快速路径。

当前状态:主要思路已经实现。全局和 secondary stream 块可以执行显式因果计划,完整残差按 64 次间隔审计;2.10 s 中快速执行 22,216 次、审计 351 次、失败和旧路径回退均为 0。仍保留 472 个运行时未知量,204 个重复 effort 坐标尚未在执行层消除,且存在清零、复制、缩放、getattr/setattr 和完整对象遍历成本。

一次已预热的 A/B 微基准显示,整个 RHS 的因果快速模式中位数约 200.8 ms/100 次,强制完整检查约 297.4 ms/100 次,即现有路径已经取得约 1.48× 的整 RHS 收益。单纯继续增大审计间隔预计收益有限。

工作项:

  • 将 68 个 effort 等价组压缩为独立运行时坐标,消除 204 个重复 effort 槽。
  • 将 200 条显式 flow/force 规则预编译为稳定顺序和整数槽索引。
  • 用预分配连续数组代替热路径对象读写、临时字典和重复缩放。
  • 仅清理会被当前计划写入的槽,避免每次全量清零和复制。
  • 保留初始化、事件后、接受步或固定间隔的完整残差审计。
  • 自定义组件、声明缺失、审计失败或奇异结构必须自动回退旧求解器。
  • 输出编译统计:消元数、显式规则覆盖率、审计率、失败原因和回退次数。

验收条件:

  • 复杂模型因果覆盖率大于 98%,完整 0.81/2.10 s 运行审计失败为 0。
  • 新旧路径的状态、事件、关键代数量和残差均满足统一数值契约。
  • 自定义组件、接触模型和非因果结构的回退测试全部通过。
  • 在完整模型上证明端到端收益;不得只提交代数微基准。

风险与回滚:别名写回、事件后模式改变和不完整依赖声明可能造成静默错误。新路径必须可通过配置关闭,并在审计失败时记录首个违规方程与变量。

指标 当前 完成后
运行时代数槽 472 待填
重复 effort 槽 204 待填
已预热 Python 调用/单 RHS 约 15,774 待填
因果审计失败 0 待填
0.81/2.10 s 墙钟中位数 63.779 / 126.211 s(单次环境值) 待填

OPT-02 建立扁平数值 IR 和数组执行内核

目标:把组件对象、字典查找和端口读写转换成稳定的数值执行计划,为 NumPy、Numba 或原生后端提供共同基础。

当前状态:构建阶段已有一定预绑定,但 RHS 仍以 Python 对象和方法调用为主。已预热、启用物性缓存时,采样剖析约有 15,774 次 Python 调用/RHS;不同缓存上下文会明显改变该数字,所以后续必须统一测量口径。

工作项:

  • 定义最小数值 IR:连续槽、常量、参数、状态、代数量、模式位和操作码。
  • 将组件方程、因果规则、stream 传播和结果提取分成明确执行阶段。
  • 先实现可逐项对照的纯 Python/NumPy 参考后端。
  • 添加 IR 与当前对象执行器逐操作/逐阶段差分测试。
  • 评估 Numba 与 C/C++ 后端;在 IR 稳定前不绑定单一编译技术。
  • 对动态自定义组件保留对象适配层和明确的性能降级提示。
  • 缓存编译结果,并以模型结构、组件版本和数值后端作为缓存键。

验收条件:

  • 全部现有组件族通过新旧执行器差分测试。
  • 事件切换后能正确重编译或选择预编译模式计划。
  • 明显降低 Python 调用数、对象分配和 RHS 中位时间,并改善完整仿真墙钟。
  • 不以牺牲异常信息、取消检查或回退能力换取速度。
指标 当前 原型后 完成后
Python 调用/单 RHS 约 15,774 待填 待填
临时分配字节/单 RHS 待测 待填 待填
RHS 中位时间 约 2 ms(现有微基准口径) 待填 待填
2.10 s 积分时间 122.180 s 待填 待填

OPT-03 稀疏 Jacobian 数值层与解析/半解析演进

目标:先建立可审计、可回滚的 callable sparse Jacobian 数值层,再逐步把组件、因果代数计划、stream 和物性的局部导数传播进来。完整稀疏有限差分、受审计 secant 和真正的解析/半解析 Jacobian 是三个不同阶段,必须分别记录和验收。

当前状态:数值层基础与实验候选已经实现;首批“证明门控”的三活塞 6 列半解析切片已经接入,但通用组件、stream SCC 和其余状态列仍未覆盖,因此 OPT-03 总体继续标记为“部分实现”。默认执行路径继续使用 SciPy jac_sparsity,半解析路径只允许通过 SIMULATION_ODE_JACOBIAN_MODE=semi-analytic 显式启用。

现有实现包括:

  • direct 和 stepwise BDF/Radau 均可接收 callable jac;信号断点、状态事件和可恢复重启会清空 Jacobian 数值状态并重新构建,显式积分器完全忽略该对象。
  • 新增独立的 sparse numerical Jacobian 内核,隔离并检查 SciPy 私有 num_jac/group_columns 接口。
  • 每个 solver segment 记录完整构建、有限差分扰动、基准 RHS、Jv 审计、secant 复用/失败和装配时间;SciPy 模式的估计值不再伪装成 callable 模式的真实计数。
  • 4 条无离散端挡模式歧义的机械运动学行直接装配为 d(x')/d(v)=1;带端挡的行继续数值差分。
  • callable 内核新增 exact_columns=(indices, provider):已提供精确导数的列从分组有限差分中移除,其余列仍按原始保守结构做 subset FD;原始色数、剩余色数、单次真实 FD、精确列构建及回退次数/原因都进入分段诊断。
  • 精确列提供器用类型化 ExactColumnsUnavailable 表达当前点不可用;同一次构建会恢复原始 seed 0 的完整数值 Jacobian,避免把未知导数静默当成 0。模型编译证明失败、SciPy 私有接口不兼容或配置关闭时则直接保留原生 SciPy 路径。
  • 首批目标是三条同构活塞支路的 6 个机械状态列 (20, 21, 38, 39, 54, 55)。编译器只有在组件类型、连接拓扑、因果赋值计划、机械等价组和 stream 影响范围都满足证明条件时才启用;该 XML 中共覆盖 34 条 reachable assignments,FD 颜色由 31 降至 25,另由提供器装配 6 列。
  • 已增加 Ideal/PR 介质 m/U/V 物性线性化,以及 PNRP、PNCH012、PNL0001、LSTP、MECMAS 的局部切向原语;每个原语都返回 valid/reason,以便在非光滑接触、临界流动或不支持的模式上拒绝解析近似。
  • Jacobian 内部每次 RHS 都执行取消检查;不安全的共享模型基准缓存已经撤销。随后实现的一次性 generation/dirty token 安全版本在正式 0.81 s 中 253 次 Jacobian 请求命中 0 次:BDF 首次构建前会做初始步长试算,后续构建前也会留下 Newton 试探状态,模型并不位于请求的基准点。该版本没有节省 RHS,最终也已删除。
  • SIMULATION_ODE_JACOBIAN_MODE=scipy 是默认和回滚路径;小型全稠密结构或 SciPy 私有接口不兼容时也回到该路径。

显式 SIMULATION_ODE_JACOBIAN_MODE=optimized 仍构造完整稀疏有限差分 Jacobian,不使用 secant。最终实现严格固定 SciPy seed 0,并从原始 1284 nnz 保守结构生成 31 色扰动批次;移除精确行不会重新着色。曾试验的 seed 54 为 30 色,结构虽未删边,却改变了事件敏感模型的运行轨迹,因此多 seed 自动择优已经从代码中删除。

历史 30 色候选有性能收益,但没有通过事件/状态等价验收:

  • 最终安全版本的 0.81 s 单次相邻 A/B 中,optimized 积分 55.034 s、总墙钟 56.957 s,SciPy 基线积分 59.924 s、总墙钟 61.953 s,分别约改善 8.2% / 8.1%。
  • 0.81 s 中 callable 实际 Jacobian RHS(扰动加基准)为 7,103,SciPy 估计为 8,096,约减少 12.3%;nfev/njev/nlu 为 3467/228/670,基线为 3763/253/761。
  • 两条 0.81 s 轨迹具有相同结果键、采样时刻、0 次状态切换和约 1e-16 的最大代数残差,但最终 74 维状态的最大差异为 51.59 × (atol + rtol·|y|),最差状态相对差约 5.2e-5,超过当前拟定的严格等价门槛。
  • 2.10 s optimized 仍成功越过 2.05 s,积分 115.928 s,而 SciPy 基线为 122.180 s;但 optimized 出现 4 次状态切换、7 次 solver 启动和 215 个样本,基线为 2 / 5 / 213。因此该候选的事件等价验收失败,不能设为默认。
  • 短变体隔离显示:seed 0 callable(有或没有 4 条精确行)在 0.01 s 的最终 74 维状态与 SciPy 逐项一致;轨迹分叉来自 30 色 seed 54,而不是精确运动学行。这提示事件敏感模型需要更多运行中 Jacobian 漏边/弱依赖审计,不能只依赖初始点结构测试。

最终 seed 0 安全候选的正式 0.81 s 探针与 SciPy 基线具有相同的物理解哈希 c6354c97...、3763/253/761 的 nfev/njev/nlu、1076 个接受步、3 次 solver 启动、0 次状态切换和 30,502 次压力闭合。实际 Jacobian 内部 RHS 为 7,872 + 253 = 8,125;安全 token 缓存命中为 0。积分时间 60.972 s、探针总墙钟 62.945 s,相邻 SciPy 基线为 59.924/61.953 s,没有净收益并略有退化。因此安全缓存已删除,seed 0 callable 只保留为后续解析行接入与诊断基础,不进入默认路径;无需为一个已经失败收益门槛的候选继续做 2.10 s 性能复测。

SIMULATION_ODE_JACOBIAN_MODE=hybrid 另提供实验性的数值 secant 原型:最多连续复用一次,复用前执行确定性方向 Jv 审计,失败或审计无信息量会在同一次调用中完整刷新。目标模型的早期探针中候选审计普遍失败;用 seed 0 的旧完整 Jacobian 做 0.01 s 探针时,39 次复用审计全部失败,额外产生 39 次 Jv RHS,实际复用仍为 0。因此它目前既不是解析 Jacobian,也没有可声明的端到端收益。

已完成的数值层工作:

  • direct/stepwise BDF、Radau callable jac 接线;显式方法隔离。
  • breakpoint、事件、可恢复重启后的强制重建与分段计数。
  • 完整稀疏有限差分内核、严格 seed 0 着色、4 条安全精确行。
  • exact-columns subset FD、类型化同次完整回退和原始/剩余色数及回退诊断。
  • 真实 RHS/装配计数,以及 SciPy 估计口径分离。
  • Jacobian 内部有界取消检查;撤销不安全缓存及命中为 0 的安全 token 缓存。
  • 稠密结构、兼容问题和配置关闭时保留 SciPy 路径。
  • 最多一次复用、Jv 审计、无信息审计拒绝和失败完整刷新测试。
  • 复杂 XML 0.81/2.10 s 单次性能与事件探针。
  • 同一代码版本完成 3 组相邻 0.81 s A/B,报告中位数与范围。
  • 为事件敏感模型定义并通过状态、事件时刻/顺序和模式等价契约。
  • 在正式锁定环境完成独立预热后的 3 次 A/B,复核中位数与离散度。

解析/半解析后续工作:

  • 为首批 Ideal/PR、PNRP、PNCH012、PNL0001、LSTP、MECMAS 路径定义带有效性诊断的局部切向契约。
  • 对目标三活塞 6 列沿 34 条可证明因果赋值传播导数,并从 FD 分组中排除这些列。
  • 将局部导数/JVP 契约扩展到其余基础与自定义组件。
  • 将因果传播推广到目标切片以外的状态列和代数计划。
  • 对 stream SCC 推导显式或隐式小块导数。
  • 对物性函数提供解析导数、可靠自动微分或受控局部差分接口。
  • 在接触、饱和、开关和临界模式附近使用分段导数与局部回退。
  • 对自定义组件缺失的导数声明生成明确诊断,不得静默置零。
  • 在 0.68–0.71、0.79–0.81、事件两侧和 2.00–2.10 s 检查点执行稠密数值漏边审计与随机方向 JVP。

验收条件:

  • 历史 external-volume 跨域结构护栏与初始点稠密数值漏边测试继续通过。
  • callable 接线、分段重置、取消、显式方法隔离、secant 上限和审计失败回退有自动测试。
  • 0.81/2.10 s 的连续状态、事件时刻/顺序、模式和残差满足统一契约;当前 30 色候选未通过。
  • 默认候选在锁定环境的 3 次中位墙钟有净收益,小模型无显著退化。
  • 首批目标切向原语和 6 列通过逐列中心差分、模式分支与局部回退验证。
  • 通用组件级解析/半解析导数通过随机方向 JVP、逐列抽查和局部回退验证。

风险与回滚:历史 external-volume 漏边说明“颜色更少”本身不是正确性证据。不同合法颜色组合也可能暴露保守结构中未声明的弱依赖,并改变非光滑接触附近的事件序列。默认保持 scipy;optimized/hybrid 仅显式实验。非光滑点的解析或 secant 近似未必可靠,事件分段重置、审计和旧路径必须长期保留。

历史实验指标 SciPy 基线 已撤销的 30 色候选 验收
保守结构 / 实际 FD 颜色 1284 nnz / 31 1284 nnz / 30(seed 54) 结构不删边
精确装配行 0 4 条运动学行 短变体证明不改变轨迹
0.81 s Jacobian RHS(含基准) 估计 8,096 实际 7,103 -12.3%
0.81 s nfev/njev/nlu 3763 / 253 / 761 3467 / 228 / 670 工作量下降
0.81 s 积分 / 总墙钟 59.924 / 61.953 s 55.034 / 56.957 s 单次约 -8.2% / -8.1%
0.81 s 最大最终状态误差尺度 参考 51.59 未通过
2.10 s Jacobian RHS(含基准) 估计 15,584 实际 14,556 -6.6%
2.10 s nfev/njev/nlu 6734 / 487 / 1507 6606 / 468 / 1469 工作量小幅下降
2.10 s 积分时间 122.180 s 115.928 s 单次约 -5.1%
2.10 s 状态切换 / solver 启动 / 样本 2 / 5 / 213 4 / 7 / 215 未通过
最终安全候选指标(0.81 s) SciPy 基线 seed 0 callable 验收
保守结构 / FD 颜色 1284 nnz / 31 1284 nnz / 31(seed 0) 相同扰动批次
nfev/njev/nlu 3763 / 253 / 761 3763 / 253 / 761 相同
接受步 / solver 启动 / 状态切换 1076 / 3 / 0 1076 / 3 / 0 相同
压力闭合 30,502 30,502 相同
物理解哈希 c6354c97... c6354c97... 通过
安全基准 RHS 缓存命中 不适用 0 / 253 无收益,代码已删除
积分 / 探针总墙钟 59.924 / 61.953 s 60.972 / 62.945 s 略有退化,未通过收益门槛

2026-08-17 / 工作树基于 6bb0591d

  • 状态:未开始 → 部分实现(数值接入层完成;30 色候选未通过事件等价,seed 0 候选未通过收益门槛;解析/半解析传播未开始)
  • 代码备份:backup/jacobian-before-20260817-6bb0591,精确指向 6bb0591d320d0c448ee8d224dd44127bfe3ce00f。该分支只备份 tracked 代码基线,不包含当时未跟踪的本文档。
  • 运行环境:Python 3.12.3、NumPy 2.4.6、SciPy 1.17.1;输入 SHA-256 2fb95e65...;2.10 s 仅内存覆盖停止时间,磁盘 XML 未修改。
  • 正确性结果:Jacobian 内核、core solver、Generic sparsity 和 Generic XML 共 57 项通过;压力因果、stream 块、机械接触、PNRP17、代数稀疏与方程块另 52 项通过,external-volume 漏边护栏继续通过。热流体闭合计划 13 项中 12 项通过,剩余 1 项因用户已将 fixture 移至 tests/data/fixtures/、旧测试仍读取 tests/fixtures/ 而报既有 FileNotFoundError,与本次改动无关。30 色候选在 2.10 s 的事件数由 2 变为 4;最终 seed 0 候选在 0.81 s 恢复相同物理解哈希与求解统计。
  • 性能结果:见上表。数字均为同机相邻单次结果,不是 3 次中位数;最终 seed 0 候选没有减少求解工作并略慢。
  • 卡死结果:历史 30 色探针在 2.040187 s @ 106.499 s、2.051323 s @ 113.996 s、2.065299 s @ 115.472 s 持续推进并完成到 2.10 s;默认 SciPy 的正式探针同样越过 2.05 s 并完成,无重试、无死锁。
  • 安全收口:默认保持 SciPy;移除多 seed 自动择优、不安全共享缓存和零命中的安全 token 缓存;Jacobian 内部保留取消检查;无信息 Jv 审计强制刷新;显式 solver 不观察或重置 Jacobian。
  • 决策:保留严格 seed 0 的 callable/诊断/精确行基础和显式实验开关;30 色、基准缓存与 secant 均不进入默认路径。下一阶段优先建立多检查点弱依赖审计和组件级局部导数,不再以颜色数或数值缓存单独作为优化成功标准。
  • 证据文件:app/simulation/solvers/jacobian.py、app/simulation/solvers/solver.py、app/simulation/systems/generic.py、tests/test_sparse_secant_jacobian.py、tests/test_core_solver.py、tests/test_generic_jacobian_sparsity.py、tests/test_generic_system_xml_simulation.py

2026-08-17 / 首批三活塞半解析 6 列切片

  • 状态:部分实现 → 部分实现(首批目标切片完成并通过局部导数验证;OPT-03 的通用解析/半解析覆盖尚未完成)。
  • 实现范围:新增 exact-columns subset FD 接口、类型化同次完整数值回退和分段诊断;为三条目标活塞支路编译状态列 (20, 21, 38, 39, 54, 55),沿 34 条可达因果赋值传播切向量,使剩余 FD 颜色从 31 降到 25。
  • 局部导数:实现 Ideal/PR 介质 m/U/V 物性线性化,以及 PNRP、PNCH012、PNL0001、LSTP、MECMAS 的几何、压力、质量/能量、流量/力和接触模式切向原语;原语显式报告 valid/reason。
  • 证明与回退:组件类型、连接拓扑、因果计划、机械组和静态 stream 影响范围必须全部满足编译证明。causal/stream/custom/兼容性证明不成立时不安装 callable,继续使用原生 SciPy;运行点进入非光滑接触边界、临界流动、陈旧 primal 或其他不支持模式时抛出类型化 ExactColumnsUnavailable,同一次构建恢复原始 seed 0 完整数值 Jacobian。任何不可证明项都不会静默填 0。
  • 配置边界:默认仍为 SIMULATION_ODE_JACOBIAN_MODE=scipy;首批路径仅通过 semi-analytic 显式 opt-in,不替换生产默认值。
  • 自动测试:focused 套件 86 项、adjacent 套件 164 项,共 250 项通过。热流体 closure 计划另为 12/13 项通过;唯一失败仍是旧测试读取 tests/fixtures/、而 fixture 已被用户移至 tests/data/fixtures/ 导致的既有 FileNotFoundError,与本轮 Jacobian 改动无关。
  • 局部正确性:在平滑检查点,SciPy 分组有限差分漏掉 J[19,20] ≈ -3201.486;半解析列相对独立中心差分的最大相对误差为 1.897e-8。inactive/active 接触分支、过期 primal、非因果计划和不支持拓扑均覆盖了成功或回退路径。
  • 轨迹正确性:默认容差下,两条 0.81 s 轨迹最差点为 t=0.65 s 的能量状态 state[33],原始相对差 8.24e-5,缩放误差 82.36;事件数和顺序一致,但尚未满足拟定的严格逐点轨迹门槛。提高精度后互差收敛:rtol=1e-7 时最大绝对/相对差为 0.081965 / 1.592e-6,rtol=1e-8 时为 0.0175357 / 3.09062e-7,分别缩小约 4.67× / 5.15×,且两组事件均一致。这支持“求解路径差异随容差收敛”,但不足以把候选升为默认。
  • 性能口径:0.81 s 已在同机、同一工作树连续完成 3 组相邻 A/B;表中时间为中位数,括号给出 3 次范围。测试使用现有 /opt/srm-trial-review/.venv,没有独立预热且依赖版本未由项目锁文件固定,因此仍需在正式锁定环境复核,不能单独作为切换默认值的依据。2.10 s 为最终 one-shot primal 捕获版本的单次复跑;此前数学路径相同的预备运行墙钟为 111.068 s,本次为 116.512 s,长程时间仍需重复测量。
最终 0.81 s 三次指标 SciPy 基线 semi-analytic 候选 变化/说明
FD 颜色 / 精确状态列 31 / 0 25 / 6 目标列为 20、21、38、39、54、55
nfev/njev/nlu 3763 / 253 / 761 3650 / 228 / 711 求解工作下降
接受步 / solver 启动 / 状态事件 / 样本 1076 / 3 / 0 / 82 1056 / 3 / 0 / 82 事件和输出网格一致
Jacobian RHS 8,096(估计) 5,985(实计) -26.1%
精确列构建 / 类型化回退 不适用 224 / 4 4 次恢复完整数值构建
压力闭合 30,502 25,672 -15.8%
积分时间中位数(范围) 59.725 s(59.568–60.188) 55.631 s(55.432–56.307) 中位数 -6.85%
总墙钟中位数(范围) 61.203 s(61.070–61.704) 56.708 s(56.508–57.410) 中位数 -7.34%;逐组改善 6.96%–7.47%
延长至 2.10 s 单次指标 SciPy 基线 semi-analytic 候选 变化/说明
状态 完成,越过 2.05 s 完成,越过 2.05 s 最终版本越过 2.05 s 的墙钟为 111.660 s
nfev/njev/nlu 6734 / 487 / 1507 6246 / 445 / 1328 求解工作下降
接受步 1857 1753 -104
solver 启动 / 状态切换 / 样本 5 / 2 / 213 5 / 2 / 213 事件计数和输出网格一致
Jacobian RHS 15,584(估计) 11,771(实计) -24.5%
类型化回退 不适用 26 非平滑/不支持点恢复完整数值构建
压力闭合 57,601 48,248 -16.2%
积分时间 122.180 s 112.825 s 单次 -7.7%
总墙钟 126.211 s 116.512 s 单次 -7.7%
  • 卡死复核:最终 semi-analytic 候选在墙钟 111.660 s 越过模拟时刻 2.05 s,随后于 116.512 s 完成到 2.10 s;与 SciPy 基线一样未出现无进度死锁。
  • 未覆盖范围:通用 stream SCC 导数、目标三支路以外的组件/状态列、自定义组件导数契约、正式锁定环境的独立预热复测,以及 10 s 长时模式覆盖。
  • 决策:保留首批半解析切片和自动回退作为显式实验路径;OPT-03 继续为“部分实现”,默认继续使用 SciPy。完成上述通用覆盖、严格轨迹契约和重复基准前,不切换默认值。
  • 代码备份:仍使用进入 Jacobian 优化前建立的 backup/jacobian-before-20260817-6bb0591,精确指向 6bb0591d320d0c448ee8d224dd44127bfe3ce00f。
  • 证据文件:app/simulation/solvers/jacobian.py、app/simulation/solvers/tangent.py、app/simulation/solvers/solver.py、app/simulation/systems/generic.py、app/simulation/core/medium.py、app/simulation/components/amesim/media/mediums.py、app/simulation/components/amesim/mechanical/pistons.py、app/simulation/components/amesim/storage/chambers.py、app/simulation/components/amesim/flow/pipes.py、app/simulation/components/amesim/mechanical/translational.py、tests/test_sparse_secant_jacobian.py、tests/test_analytic_tangent_primitives.py、tests/test_three_piston_tangent.py

OPT-04 stream 拓扑传播与物性成组复用

目标:让无环 stream 网络一次传播,只对真正的强连通块迭代;同一状态反算的物性量成组计算和复用。

当前状态:stream 求解器已预绑定组件、端口和连接,物性层也有单次运行精确缓存;但每次求解仍构造临时字典/列表、重复调用连接焓计算,尚未编译 SCC/DAG。热流体外层固定点最多 25 次,本模型实测最多 3 次。

工作项:

  • 构建 stream 图的 SCC,并将缩点图编译为拓扑顺序。
  • 对单节点和无环段使用一次传播,仅在循环 SCC 内迭代。
  • 使用预分配数组和原地误差统计,避免每轮临时字典/列表。
  • 缓存同一求解阶段的连接焓结果,避免返回前重复计算。
  • 将 p/T/rho/h/s 等同源物性组织为状态包,按精确输入键成组复用。
  • 增加缓存命中、SCC 迭代、失效原因和物性调用次数指标。
  • 评估脏标记传播,但必须证明事件和反向流切换时不会复用陈旧值。

验收条件:

  • 无环、单环、多环、反向流和事件后拓扑测试全部通过。
  • 复杂模型的最大 stream/热流体迭代不增加,残差不恶化。
  • 量化减少物性调用、临时分配、压力闭合或 RHS 时间。
指标 当前 完成后
stream 块 / 未知量 9 / 192 待填
最大热流体迭代 3 待填
2.10 s 压力闭合 57,601 待填
物性调用 / 缓存命中率 待测 待填

OPT-05 状态缩放、分量容差和步长策略

目标:减少量纲差异造成的不必要小步和 Jacobian 重建,同时维持事件与守恒精度。

当前状态:模型中不同物理量的量级差异大。历史试验显示机械绝对容差放宽可能带来约 16% 收益,但属于精度策略变化;热流体固定点容差的简单放宽曾使表现变差,不能直接采用。

工作项:

  • 按状态物理量、标称值和工程容差建立分量 atol/缩放规则。
  • 为未提供标称值的组件定义安全默认值并输出诊断。
  • 分开积分误差、代数残差、stream 固定点和事件定位容差。
  • 统计限制步长的状态分量、误差拒步和 Jacobian 重建原因。
  • 对事件前后、接触临界区和稳态区分别评估步长上限策略。
  • 建立严格/标准/快速配置,但默认配置必须有明确精度契约。

验收条件:

  • 每个配置都有状态、事件、残差和守恒误差界限。
  • 标准配置在复杂模型上减少拒步或分解工作,不引入模式遗漏。
  • 所有收益报告同时给出误差变化,禁止只报告墙钟。

OPT-06 事件检测与 dense output 按需化

目标:避免在绝大多数没有事件候选、也不跨输出采样点的接受步上创建 dense output。

当前状态:已有事件候选筛选和部分非事件优化,但只要存在状态转换处理器,接受步仍可能构造 dense output。2.10 s 有 1857 个接受步而只有 2 次状态切换,存在减少插值构造的空间。

工作项:

  • 在构造 dense output 前执行低成本端点符号/模式候选检查。
  • 仅在跨输出采样点或存在事件候选时创建插值器。
  • 将输出插值与事件定位的生命周期和精度需求分离。
  • 统计候选数、误报数、定位次数、dense output 构造数和耗时。

验收条件:

  • 同时事件、擦边事件、抖动防护和多模式顺序测试通过。
  • 事件时刻误差不超契约,事件顺序和最终模式不变。
  • 完整模型 dense output 构造数与耗时明显下降。

OPT-07 输出、后处理和传输内存优化

目标:在长仿真中控制结果生成、JSON 编码、前端复制和峰值内存。

当前状态:当前模型有 1,021 个结果变量;10 s / 0.01 s 约产生 1,022,021 个标量。现路径会对每个样本重新闭合、追加全部结果,并把完整结果作为一个 NDJSON 消息发送。它不是本次 2.05 s 慢推进的主因,但会成为长时间运行的显著成本。

工作项:

  • 支持结果变量白名单、分组和按需派生量。
  • 将积分内部采样、结果存储采样和显示采样分离。
  • 对显示路径提供服务端降采样,同时保留可选完整数据模式。
  • 分块编码和传输结果,或返回 resultId 后分页/流式获取。
  • 评估前端 TypedArray/列式数据,减少嵌套对象和重复复制。
  • 避免后处理中对每个样本重复执行不必要的完整闭合。
  • 记录原始标量数、编码/传输字节数、后处理时间和峰值 RSS。

验收条件:

  • 完整输出模式保持现有 API 契约,或通过显式版本升级迁移。
  • 精简模式的变量选择和降采样行为可预测、可测试。
  • 10 s 基准中后处理时间、传输字节和峰值 RSS 有量化改善。

OPT-08 进度、取消和服务并发鲁棒性

目标:区分“内部慢步”和“真正无进度”,并让长任务可取消、可限流、不会拖垮服务进程。

当前状态:已有 stream 进度和取消检查;前端无进度阈值约 60 s。本次 2.05 s 附近可见最大间隔约 7.5 s,且中间有接受步与 CPU 活动,因此没有触发真实无进度条件。

工作项:

  • 分别上报模拟时间、接受步、内部 RHS/闭合活动和墙钟心跳。
  • 将“运行中但步很慢”与“求解器无活动”使用不同状态和超时策略。
  • 在代数闭合、stream 迭代、Jacobian 构建和后处理内加入有界取消检查。
  • 限制并发仿真 worker、队列长度和单任务 CPU/内存预算。
  • 超时报告最后活动阶段、模拟时刻、步长和关键计数,而非只返回通用错误。
  • 添加故意慢 RHS、死循环防护、客户端断连和多任务竞争测试。

验收条件:

  • 正常慢步不会被误判为死锁,真实无活动能在约定时间内终止并给出诊断。
  • 取消请求在每个主要阶段都能在有界时间内生效。
  • 并发压力下服务仍能响应健康检查和新请求拒绝/排队逻辑。

OPT-09 建立 10 s 长时验证与模式覆盖

目标:用实测替代“0.81 s 或 2.10 s 可以外推到 10 s”的假设。

当前状态:2.10 s 已成功;10 s 尚未运行和建立资源预算。模型可能在后续出现新的事件、模式、接触切换或数值尺度问题。

工作项:

  • 在正式锁定环境运行未优化基线 10 s,设置心跳、资源上限和可恢复日志。
  • 保存事件、模式、步长、拒步、Jacobian、闭合和内存随模拟时间的时间线。
  • 为长跑设置阶段性检查点,支持定位首次偏差而非只比较终点。
  • 将每项 P1 优化分别加入 10 s A/B,不把多个改动混成一个结果。
  • 根据首次基线制定合理的 CI 频率和资源门槛。

验收条件:

  • 连续 3 次完成 10 s,没有无解释回退、NaN/Inf 或资源失控。
  • 全程模式、事件、关键状态和守恒量满足契约。
  • 可从日志快速判断任何慢区属于积分、Jacobian、闭合、事件还是输出。

OPT-10 明确高指数 DAE 和强非光滑系统边界

目标:明确当前通用求解能力的工程边界,并决定是否值得引入真正的 DAE/互补问题求解器。

当前状态:当前架构更适合结构明确、可唯一闭合、状态较连续的规则 index-1 类系统。超硬非光滑接触、临界抖动、近奇异代数系统、更高指数 DAE 和依赖声明不完整的自定义组件仍是薄弱点。

工作项:

  • 建立小型基准族:刚性接触、反复开闭、近奇异闭合、尺度跨越、自定义漏依赖和 index-2/3 示例。
  • 对每类系统定义“支持”“降级支持”“明确拒绝”,并给出诊断。
  • 评估质量矩阵 DAE、指数约简、互补/半光滑方法与现有架构的成本。
  • 只有真实模型需求和基准证明必要时,才启动通用 DAE 后端项目。

验收条件:

  • 文档与运行时错误能明确说明能力边界,不出现静默错误。
  • 若启动新后端,有独立设计、基准和迁移计划,不与普通 RHS 性能优化混合。

6. 统一回归矩阵

场景 结构 数值状态 事件/模式 回退 性能 长时内存
小型线性组件 必测 必测 不适用 必测 冒烟 不适用
非线性压力/流量 必测 必测 可选 必测 必测 可选
stream 无环/成环/反向流 必测 必测 必测 必测 必测 可选
接触与模式切换 必测 必测 必测 必测 必测 可选
自定义组件与漏依赖 必测 必测 可选 必测 可选 不适用
本文复杂 XML 0.81 s 必测 必测 必测 必测 必测 必测
本文复杂 XML 2.10 s 必测 必测 必测 必测 必测 必测
本文复杂 XML 10 s 必测 必测 必测 必测 必测 必测

当前相关回归套件包括:

  • tests/test_sparse_secant_jacobian.py
  • tests/test_generic_jacobian_sparsity.py
  • tests/test_pressure_flow_causal_execution.py
  • tests/test_stream_pressure_block_solver.py
  • tests/test_core_solver.py

这些测试目前覆盖部分关键机制,但不能替代复杂 XML 的端到端数值和长时回归。

7. 单项更新模板

完成一个原型或 PR 后,在对应任务下追加以下记录:

#### YYYY-MM-DD / <commit-or-branch>

- 状态:未开始 → 进行中 / 部分实现 → 已完成
- 实现范围:
- 未覆盖范围:
- 运行环境:
- 输入与配置:
- 正确性结果:
- 性能结果(中位数与离散度):
- 回退/审计结果:
- 风险或已知退化:
- 决策:合入默认路径 / 继续实验 / 回滚 / 不采用
- 证据文件或 CI 链接:

8. 总体更新记录

日期 代码/分支 任务 变化 正确性 性能 决策
2026-08-17 6bb0591d 基线 原始 0.81 s 完成;内存延长 2.10 s 完成并越过 2.05 s 无卡死;当前环境哈希与历史不同,待正式环境复核 63.779 s / 126.211 s(单次) 建立任务清单,先完成 OPT-00
2026-08-17 工作树基于 6bb0591d;备份 backup/jacobian-before-20260817-6bb0591 OPT-03 callable sparse Jacobian、真实计数、分段重置、取消、严格 seed 0 与实验 secant 121 项相关测试通过;另 1 项既有 fixture 路径错误;30 色候选事件不等价,seed 0 候选恢复相同哈希 30 色历史候选有收益但不正确;seed 0 候选略慢且缓存 0 命中 默认 SciPy;移除多 seed/缓存;保留接入基础;解析/半解析继续后续
2026-08-17 工作树基于 6bb0591d;同一备份分支 OPT-03 首批半解析切片 exact-columns subset FD、类型化回退/诊断、三活塞 6 列与 34 条因果赋值;31→25 个 FD 颜色;新增 Ideal/PR、PNRP、PNCH012、PNL0001、LSTP、MECMAS 切向原语 focused 86 + adjacent 164 = 250 项通过;closure 12/13,唯一失败为既有 fixture 路径;局部列对中心 FD 最大相对误差 1.897e-8;默认容差轨迹仍超严格逐点门槛,但随 rtol 收紧约 4.67×/5.15× 收敛且事件一致 0.81 s 三次墙钟中位数 61.203→56.708 s,Jac RHS 8096(估计)→5985(实计);最终 2.10 s 单次 126.211→116.512 s,正常越过 2.05 s,事件/启动/样本均与基线一致 首批目标切片完成,OPT-03 总体仍部分实现;默认 SciPy,semi-analytic 显式 opt-in;待通用 stream/其余列、正式锁定环境独立预热和 10 s 验证
2026-08-17 同一 OPT-03 工作树;3 组相邻 A/B OPT-03 重复性能复核 原始 0.81 s,每组先 SciPy 后 semi-analytic,运行期间无并发仿真负载 三组求解统计、哈希、事件和输出网格各自完全稳定;Jacobian RHS 8096(估计)→5985(实计) 总墙钟中位数 61.203→56.708 s(-7.34%),积分中位数 59.725→55.631 s(-6.85%) 保持显式 opt-in;仍需正式锁定环境独立预热、严格轨迹契约和 10 s 验证

9. 相关文档