Files
SystemSimulationApp/docs/other/求解器时间剖析与计数调查-2026-09-16.md
ljz 1aac220084 优化 Jacobian 确定性复用并补充性能剖析与平台依赖文档
在单次 Jacobian 构建内按完整输入精确复用储气物性、PH 反算、密度和管路求根结果,保持原有求值副作用、差分政策与失败回退。八路模型求解 CPU 中位数减少 19.27%,循环和不循环的完整原始采样均与恢复基线一致。

增加独立的跨平台时间剖析工具,记录互斥阶段耗时、Newton/LU 统计、矩阵复用与内核复用,保存 UD00 两种工况的调查报告和机器可读汇总。

补充 Windows/Linux 运行、测试、原生编译和剖析所需依赖文档及索引,不修改依赖清单、版本锁或安装环境。

验证:8 项新增专项回归通过;2270 次完整 Jacobian 核对零差异;16 次剖析配对及预热运行保持完整数值一致。既有固定样本哈希失败和 Linux 实机验收限制见报告。
2026-09-16 13:39:53 +08:00

11 KiB
Raw Permalink Blame History

求解器时间剖析与计数调查

日期:2026-09-16。

结论

方向二优化后的当前求解器,主要成本仍是 Jacobian 基准/扰动求值、普通 residual 求值,以及接受步物性检查。两种工况下它们合计占完整原生运行约 78%–81%。Dense LU 分解与线性求解合计约 5%–6%;Newton 控制、事件检测及步长/阶数控制所占比例很小。

本轮交付独立诊断工具和调查结果。计时加入 test/ 下的源码副本,当前生产求解器未额外修改。方向一仍保存在 stash@{0}(06b161c309644bb01aa402ff79f34749ff8e889a)。

工况、测量与数值保持

  • 当前八路模型:132 个状态、1784 个输出;Windows 11,CVODE 7.4 BDF。
  • 两个 UD00 均不循环、两个 UD00 均循环,分别运行 0–21.7 s,覆盖 10.8 / 21.6 s 边界。
  • 采样间隔 0.01 s,rtol 1e-8,保持既有 atol,max_step 1e30。
  • 所有构建结束后,每种工况各进行一组预热和三组正常/插桩串行配对测量;预热排除。
  • 16 次运行的完整结果 JSON(仅排除计时字段)、全部状态/输出二进制、警告及原有计数均通过一致性检查。
  • 两种工况每次重复的新计数也完全一致。原始源码哈希及生成 C/头文件已核对。
  • 计时器嵌套、提前返回、goto 清理及源码锚点保护测试:2 项通过。

以下 Total simulation 指原生进程内从初始化到结果写出和清理的完整工作,不含构建、进程启动、API 和浏览器。各阶段采用单调墙钟,使用扣除子调用后的互斥时间;三次取平均,分项可加总。求解/进程总时长中位数另列。

时间树

UD00 不循环

Total simulation  7.656251 s  (100%)
├── symbolic factorization                  N/A(Dense LU)
├── error estimation 独立计时                未分离,包含在下方 CVODE controller 组
├── residual evaluation                         2.087807 s   27.27%
├── Jacobian assembly (含探针)                     2.739999 s   35.79%
├── numerical factorization                     0.236525 s    3.09%
├── linear solve                                0.179552 s    2.35%
├── linear setup / 矩阵缩放等                        0.106778 s    1.39%
├── Newton overhead                             0.012538 s    0.16%
├── CVODE controller / error estimation 等       0.021977 s    0.29%
├── event detection                             0.001957 s    0.03%
├── accepted-step property checks               1.171337 s   15.30%
├── sampling / storage                          0.009698 s    0.13%
├── output replay                               0.298776 s    3.90%
├── result encoding / 写出                        0.777299 s   10.15%
├── poll / progress                             0.006268 s    0.08%
└── framework / other                           0.005739 s    0.07%

其中积分循环平均耗时为 6.578949 s。

UD00 循环

Total simulation  9.711949 s  (100%)
├── symbolic factorization                  N/A(Dense LU)
├── error estimation 独立计时                未分离,包含在下方 CVODE controller 组
├── residual evaluation                         2.832336 s   29.16%
├── Jacobian assembly (含探针)                     3.431087 s   35.33%
├── numerical factorization                     0.329359 s    3.39%
├── linear solve                                0.240836 s    2.48%
├── linear setup / 矩阵缩放等                        0.143107 s    1.47%
├── Newton overhead                             0.016226 s    0.17%
├── CVODE controller / error estimation 等       0.028732 s    0.30%
├── event detection                             0.002641 s    0.03%
├── accepted-step property checks               1.620996 s   16.69%
├── sampling / storage                          0.009675 s    0.10%
├── output replay                               0.297087 s    3.06%
├── result encoding / 写出                        0.743466 s    7.66%
├── poll / progress                             0.008575 s    0.09%
└── framework / other                           0.007827 s    0.08%

其中积分循环平均耗时为 8.670143 s。

关键边界

  • residual 行是普通 RHS 加非线性 residual 的代数组装,不包含 Jacobian 探针。
  • Jacobian 行包含基准/扰动模型求值和矩阵装配;普通 residual 与它不重复相加。
  • symbolic factorization 不适用于当前稠密 LU,并非已经测出一个稀疏符号分解耗时为零。
  • 误差估计在预编译 SUNDIALS 内部无独立计时入口,记录为 null;CVODE controller 还包含预测、历史更新、步长/阶数控制等,不能把整组冒称为误差估计。
  • Newton overhead 已扣除 residual、Jacobian、线性 setup、分解和回代;包括剩余收敛判断、控制和接口开销。
  • 事件检测已扣除物性检查及普通采样。result encoding 包含 JSON 序列化和文件写出,不能解释为纯编码算法的 CPU 耗时。

求解计数

参数 不循环 循环
accepted_steps 11006 15733
application_accepted_steps 11006 15731
same_time_returns 0 2
rejected_steps 1063 1563
error_test_failures 884 1334
nonlinear_step_failures 179 229
residual_evaluations 20048 28023
nonlinear_residual_calls 20037 28003
jacobian_probe_evaluations 30044 38472
jacobian_evaluations 1073 1374
jacobian_reuses 2214 3326
LU_factorizations 3287 4700
LU_solves 20037 28003
newton_solve_calls 12069 17296
newton_iterations 20037 28003
newton_failures 978 1218
event_count 1 4
scheduled_boundary_count 3 5
event_detection_calls 11006 15731
accepted_property_checks 11007 15732
solver_starts 5 10
all_counted_model_evaluations 50092 66495
sample_count 2172 2175

两种工况的 linear_setup_failures、LU_factorization_failures、LU_solve_failures、linear_rhs_evaluations、计数接口错误均为 0。

三处容易误读的计数

  1. rejected_steps 不等于旧 rejectedSteps。 旧字段仅含误差检验失败:884 / 1334;加上非线性求解导致的步失败 179 / 229,本次完整拒绝尝试计数为 1063 / 1563。Newton 内部失败 978 / 1218 可能通过刷新 J 重试恢复,不全部导致拒绝步。
  2. 循环的内部成功步 15733 与应用接受步 15731 都保留。 差额对应两次 same_time_returns;原应用对时间未推进的返回不执行接受步事件/采样流程。这不是插桩造成的轨迹变化。
  3. jacobian_reuses 是矩阵复用。 统计成功线性 setup 前后 J 刷新计数未增加的次数,分别为 2214 / 3326;它与计算新 J 时的物性内核复用不同。LU_solves 直接统计 Dense solve 调用,不能以 Krylov 迭代次数代替。

额外一致性关系在本次两种工况均成立:

  • Newton solve 调用数 = CVODE 内部成功步 + 两类拒绝步。
  • LU 分解次数 = Jacobian 刷新 setup + 沿用 J 的 setup。
  • 原 nfev = 普通 RHS + Jacobian 探针(本模型无额外摩擦求值)。
  • 累加计数段数 = solver_starts;覆盖所有事件及预定时间边界的 ReInit。

方向二内核复用

内核 不循环:计算 / 复用 循环:计算 / 复用
gas 180304 / 1502160 230872 / 1923560
ph 105403 / 732566 136587 / 940359
density 531697 / 2979837 685389 / 3819723
pipe 235272 / 1063254 301626 / 1368464

这些内核计数仅覆盖新 Jacobian 的基准/分组探针,不代表整个运行的全部物性调用。

插桩扰动

工况 原求解中位数 插桩求解中位数 观测差值 原进程中位数 插桩进程中位数
noncyclic 6.583621 s 6.638836 s +0.84% 7.777796 s 7.830035 s
cyclic 8.631554 s 8.620837 s -0.12% 9.813596 s 9.760674 s

观测扰动约为百分之一或以内;负差值属于运行波动,不代表插桩带来优化。没有从各阶段强行扣除估算的计时器成本,小于毫秒级的项目不宜过度解释。时间树采用三次平均,此表采用中位数,且进程时长含启动,三者不应直接相减当作某个新阶段。

下一步优化判断

  1. Jacobian 仍是第一热点。 约 35%–36% 的完整运行时间位于该阶段;扣除子调用的装配/分组管理仅约 0.022 / 0.028 s,绝大多数成本仍在模型探针。下一步应继续研究受扰动依赖范围及昂贵内核的导数计算;单纯优化矩阵填充循环收益有限。
  2. 普通 residual 与接受步物性检查值得分别优化。 普通 residual 占约 27%–29%,物性检查占约 15%–17%。这支持减少诊断用途完整重算的方向,但不等于已暂存的方向一方案具有正收益;必须对具体裁剪/计算调度的新增成本再次实测。
  3. 完整运行还存在结果处理成本。 输出回放与 JSON 写出合计约 11%–14%。若目标是用户等待时间,应把这部分一起衡量;若目标只限积分内核,则排除这部分。
  4. 本规模下暂不优先更换线性求解器。 分解+回代约 5%–6%,加上线性 setup 其他工作约 7%。这限定了只优化线性代数的当前收益空间;不能推广到状态数更大的模型。
  5. 事件与控制框架当前不是主要瓶颈。 Newton 控制和 CVODE controller 各不足 0.3%,事件检测约 0.03%。应首先减少昂贵物理求值成本,而不是从这些小项着手。

工具、证据与限制

  • 使用与参数口径
  • 可复用调查工具
  • 随文保存的机器可读汇总
  • 完整原始证据:项目 test/solver-profile-20260916/,含冻结程序、每次原始文件、profile.json、measurement.json、summary.json 和构建日志。该目录按项目约定被 Git 忽略。
  • 本轮没有重新执行全仓库、Amesim 或浏览器全流程验收;这里的正确性结论是插桩与当前生产版本的完整数值保持。
  • Windows 实测通过;计时与构建代码提供 Linux 路径,真实 Linux 运行未验收。
  • 使用同一 SUNDIALS 库的 Newton 实现和公共操作表;诊断版显式挂接 Newton 便于观测,并用完整数值/计数对照检验等价性,不访问 CVODE 私有结构。

计数定义参考 SUNDIALS 7.4 CVODE 可选输出接口。