Files
SystemSimulationApp/docs/standard/native-solver-profiling.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

73 lines
6.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 原生求解器时间剖析
诊断入口:`tests/manual/profile_native_solver.py`。它冻结当前正常构建,在 `test/` 下的独立源码副本加入计时,生成分阶段耗时、求解计数、完整数值对照和插桩开销。适用于当前具有自动着色 Jacobian 的 BDF 模型;不支持的模型明确拒绝,不把无法观测的阶段报告为零。
```powershell
.\.venv-win\Scripts\python.exe tests/manual/profile_native_solver.py --run
```
默认使用 `tests/data/test-mql-8-corrected.json`,将所有 UD00 分别设为不循环、循环,仿真至 21.7 s,每个版本预热一次并测量三次。可用 `--input`、`--output`、`--stop`、`--warmups`、`--repeats` 调整。输出目录须是项目 `test/` 下的新目录,以保护既有证据。所有构建先完成,随后串行计时。省略 `--run` 只准备构建。
已有完整测量可用 `--output test/solver-profile-20260916 --report-only` 重新检查计数和生成汇总,不重新编译或运行仿真。
## 计时口径
- 总计时覆盖原生进程内的初始化、积分、采样写盘、输出回放、JSON 编码及资源释放,排除构建、进程启动、API 和浏览器。
- 采用单调墙钟:Windows 为 QueryPerformanceCounter,Linux 为 CLOCK_MONOTONIC。阶段耗时不是 CPU 采样百分比,不能与 CPU 秒数直接混用。
- 每个作用域记录包含子调用的 `inclusiveSeconds`,以及扣除子调用后的 `exclusiveSeconds`。只有互斥的 exclusive 值可相加。
- 三次阶段耗时取算术平均,确保分项之和等于总耗时;完整求解和进程耗时另报中位数。计时/统计开销仍包含在诊断结果中,以正常构建的配对运行估计扰动。
- Jacobian 阶段包含基准和分组差分的模型求值;这些求值不重复计入普通 residual 阶段。保留探针、装配及普通 RHS 的子作用域数据。
- Dense LU 没有稀疏矩阵的 symbolic factorization,记为不适用。
- 当前预编译 SUNDIALS 关闭内部 profiler。误差估计无法独立直接计时,记录为 `null`,包含在 `cvode_controller_including_error_estimation` 中。该组还包括预测、历史更新、步长/阶数控制及其他未观测内部工作,不将其整体冒称为误差估计。
- `newton_overhead` 为 Newton solve 扣除 residual、线性 setup、LU 和线性求解后的剩余时间,包括收敛判断、迭代控制及接口开销,不涵盖所有外层 CVODE 控制成本。
- 事件计时扣除了接受步物性检查、普通采样和存储;保留事件探测、定位所用插值及模式更新。物性检查独立列出,以免淹没在框架耗时中。
## 观测接口与数值核对
使用 SUNDIALS 公共 SUNLinearSolver / SUNNonlinearSolver 操作表包裹原函数。诊断副本显式挂接同一库的 `SUNNonlinSol_Newton`,保持库的 Newton 实现及默认策略,便于计时与观测线性 setup。没有读取 CVODE 私有内存布局。正常构建仍使用原来的隐式默认创建过程。
每次运行比较正常构建与诊断构建的完整结果 JSON(仅排除原有两个耗时字段),并核对状态/输出二进制文件 SHA。任何数值、警告、事件或原有求解计数变化均中止调查。计数读取在每次 CVodeReInit 之前及最终清理时累计,检查累计段数等于 solver_starts,避免仅报告最后一段。
工具对单个独立进程内的一次 BDF 求解设计;诊断全局状态不作为并发库接口使用。生产源码、生产可执行文件和模型公式不被插桩脚本改写。
## 参数定义
| 参数 | 定义 |
|---|---|
| `accepted_steps` | 累加 CVodeGetNumSteps,CVODE 成功内部步数 |
| `application_accepted_steps` | 原应用接受步数,可能受同时间返回处理影响,另行保留 |
| `same_time_returns` | CVODE 成功返回但返回时间与上一次相同的次数;此时应用保留求解器历史并继续推进 |
| `error_test_failures` | 局部误差检验失败次数,对应原 `rejectedSteps` |
| `nonlinear_step_failures` | 因非线性求解失败而拒绝的步尝试 |
| `rejected_steps` | 上述两类步失败之和,不等同于原 `rejectedSteps` |
| `residual_evaluations` | CVODE 普通 RHS 次数,包含初值/步长准备;排除 Jacobian 差分探针和事件求值 |
| `nonlinear_residual_calls` | 实际 Newton 非线性 residual 回调次数,其代数部分的时间也计入 residual 阶段 |
| `jacobian_probe_evaluations` | 自定义 Jacobian 基准/扰动 RHS 次数 |
| `linear_rhs_evaluations` | CVODE 内置线性差分 RHS 次数,与自定义探针分别记录 |
| `jacobian_evaluations` | Jacobian 矩阵刷新次数 |
| `jacobian_reuses` | 成功的线性 setup 中,没有新增 Jacobian 计算、沿用已有 J 的次数;直接比较该次 setup 前后的累计刷新计数 |
| `jacobian_kernel_reuse` | 新计算一个 J 时,对 gas/PH/density/pipe 确定性结果的计算/复用次数;与矩阵复用不同 |
| `linear_setups` | CVODE 线性求解器 setup 调用次数,对应原 `nlu` 的实际口径 |
| `LU_factorizations` | 原 Dense setup 的实际调用次数,失败次数另记 |
| `LU_solves` | 原 Dense solve 的实际调用次数,失败次数另记;不使用直接法恒为零的 Krylov 迭代数代替 |
| `newton_iterations` | 累加 CVodeGetNumNonlinSolvIters |
| `newton_failures` | 累加 CVodeGetNumNonlinSolvConvFails;一次步尝试内可能刷新 J 重试,不等于拒绝步数 |
| `newton_solve_calls` | Newton solve 入口次数,与 Newton 迭代数分别记录 |
| `event_count` | 原状态转换计数,同一时刻多个转换可合为一次;不是被发现的每个零点数量 |
| `scheduled_boundary_count` | UD00 等预定时间边界导致的额外重启次数,独立于状态转换事件 |
| `event_detection_calls` | 接受步事件检查入口次数 |
| `all_counted_model_evaluations` | 原 nfev,含普通 RHS、自定义 Jacobian 探针与摩擦事件求值;不含全部诊断/输出回放求值 |
| `accepted_property_checks` | 接受步及初始化物性检查入口次数 |
计数含义参考 [SUNDIALS 7.4 CVODE 可选输出接口](https://sundials.readthedocs.io/en/v7.4.0/cvode/Usage/index.html#optional-output-functions)。实际统计以本项目的调用边界和上述分项定义为准。
## 输出
- `prepared.json`:平台、编译器、模型参数、冻结构建哈希、原始/插桩源码哈希。
- `noncyclic/`、`cyclic/`:正常构建、诊断构建及各次运行的完整结果。
- 每次诊断的 `profile.json`:原始作用域次数、inclusive/exclusive 耗时和累计计数。
- `measurement.json`、`measurements.json`:计时、原始数据哈希及数值一致性检查结果。
- `summary.json`:互斥耗时分解、计数、分项平均值、总耗时中位数及观测扰动。
计时器及锚点保护测试:`python -m unittest tests.test_solver_profile -v`。Windows 与 Linux 使用同一源码;实际平台验收情况应以具体调查报告为准。