在单次 Jacobian 构建内按完整输入精确复用储气物性、PH 反算、密度和管路求根结果,保持原有求值副作用、差分政策与失败回退。八路模型求解 CPU 中位数减少 19.27%,循环和不循环的完整原始采样均与恢复基线一致。 增加独立的跨平台时间剖析工具,记录互斥阶段耗时、Newton/LU 统计、矩阵复用与内核复用,保存 UD00 两种工况的调查报告和机器可读汇总。 补充 Windows/Linux 运行、测试、原生编译和剖析所需依赖文档及索引,不修改依赖清单、版本锁或安装环境。 验证:8 项新增专项回归通过;2270 次完整 Jacobian 核对零差异;16 次剖析配对及预热运行保持完整数值一致。既有固定样本哈希失败和 Linux 实机验收限制见报告。
106 lines
8.3 KiB
Markdown
106 lines
8.3 KiB
Markdown
# Jacobian 确定性复用与 UD00 验收
|
||
|
||
日期:2026-09-15。
|
||
|
||
## 结论与版本
|
||
|
||
已将方向一的工作区改动(含未跟踪源文件)保存到 Git stash,再从干净基线独立实施方向二。方向二在当前八路模型上将求解 CPU 时间减少 **19.27%**,完整原生工作进程耗时减少 **17.56%**。循环和不循环的完整原始采样均与基线逐字节一致。
|
||
|
||
- 方向一备份:`stash@{0}`,固定对象 `06b161c309644bb01aa402ff79f34749ff8e889a`。
|
||
- 备份名称:`codex-direction-one-purpose-evaluation-before-jacobian-2026-09-15`。
|
||
- 恢复后的基线:`2b07d996cff295d9f401dd32edd10472238bdf2d`,分支 `system-optimization`。
|
||
- 本轮修改保留在工作区,尚未提交;未重新应用方向一。原有忽略目录中的验收数据仍保留。
|
||
- 所有“优化前”均指上述恢复基线。交付核对确认两种优化后构建的 36 个源文件哈希、输入哈希及重新生成的 `model.c` / `model.h` 与实测冻结版本一致。
|
||
|
||
## 实施范围与通用性
|
||
|
||
在一次 Jacobian 构建中记录未扰动基准的确定性结果。分组扰动后,完整输入的浮点位全部一致才复用;输入变化时调用原始计算。每次 Jacobian 请求重新清空工作区。
|
||
|
||
覆盖储气物性、压力—焓温度反算、密度,以及管路标量求根。保留原有物性缓存的查询/填充顺序、温度观察、数值有效性检查和失败行为。普通 RHS、接受步检查、输出计算继续使用原路径,原有着色、差分步长和 Dense LU 不变。
|
||
|
||
复用依据实际物理输入与完整介质参数,不依赖模型实例名称、支路数或固定拓扑。使用已有内核的新模型自动接入,无需增加注册参数或维护另一套方程;新增底层内核需要审查完整输入和副作用后才能加入复用。
|
||
|
||
工作区使用堆内存。标量缓存为 1024 槽、每次至多探测 32 槽;内存不足、表满或未命中时执行原计算。分组计算失败时沿用原有未缓存逐列差分恢复。独立矩阵核对发现差异时采用参考矩阵并关闭后续着色/复用。
|
||
|
||
本轮未引入解析 Jacobian 或自动微分。现有切换、限位及隐式求根需要先明确导数政策,再评估这些方法。实现细节见 [技术说明](../standard/native-jacobian-reuse.md)。
|
||
|
||
## 正式性能对比
|
||
|
||
环境为同一台 Windows 11 机器、CVODE 7.4 BDF。输入 `tests/data/test-mql-8-corrected.json`,132 个状态、1784 个输出,两个 UD00 均不循环。仿真 0–10 s,采样间隔 0.01 s,rtol 为 1e-8,保持原有 atol 和求解设置。
|
||
|
||
编译及重型测试结束后,每个版本预热一次,排除预热,交替串行测量三次,报告中位数。完整工作进程计时包含原始数据写盘、输出回放和 JSON 写出,排除编译、API 及浏览器。带矩阵核对的运行不参与计时统计。
|
||
|
||
| 指标 | 优化前 | 优化后 | 耗时减少 |
|
||
|---|---:|---:|---:|
|
||
| 求解 CPU | 7.296875 s | 5.890625 s | 19.27% |
|
||
| 求解实际耗时 | 7.242260 s | 5.876553 s | 18.86% |
|
||
| 完整原生工作进程 | 7.852573 s | 6.473363 s | 17.56% |
|
||
|
||
六次正式运行的完整状态文件、输出文件、最终值、物性告警及原有求解计数全部相同:1002 个采样,nfev 44467,接受步 10840,拒绝步 918,Jacobian 896,LU 3106,状态转换 1,求解器启动 4。nfev 保持不变;收益来自每次求值内部减少了昂贵计算。
|
||
|
||
该工况的 Jacobian 优化路径计数如下,范围仅为基准/分组探针,不代表整个求解器的计算量:
|
||
|
||
| 内核 | 实际计算 | 复用 |
|
||
|---|---:|---:|
|
||
| 储气物性 | 150568 | 1254360 |
|
||
| 压力—焓温度反算 | 85283 | 601820 |
|
||
| 密度 | 440295 | 2479392 |
|
||
| 管路求根 | 196345 | 884176 |
|
||
|
||
原生可执行文件由 400314 字节增至 411613 字节。构建缓存状态未配平,不据此报告冷编译性能变化。以上性能收益限于当前机器及工况,不推断所有模型的加速比例。
|
||
|
||
## UD00 循环与不循环
|
||
|
||
按实际项目 JSON 修改两个 UD00 的 `iscyclic`,通过正常生成器分别构建。每个版本、每种工况运行一次 0–21.7 s,覆盖 10.8 s 和 21.6 s 的周期边界。
|
||
|
||
| 两个 UD00 的配置 | 采样数 | 优化前 CPU | 优化后 CPU | 全部原始数据及原有计数 |
|
||
|---|---:|---:|---:|---|
|
||
| 均不循环 | 2172 | 8.093750 s | 6.453125 s | 完全一致 |
|
||
| 均循环 | 2175 | 10.796875 s | 8.750000 s | 完全一致 |
|
||
|
||
这些时间是单次工况观察,正式性能结论使用上一节的三次中位数。
|
||
|
||
- 不循环:nfev 50092,接受步 11006,拒绝步 884,Jacobian 1073,LU 3287,状态转换 1,求解器启动 5。
|
||
- 循环:nfev 66495,接受步 15731,拒绝步 1334,Jacobian 1374,LU 4700,状态转换 4,求解器启动 10。
|
||
- 完整比较包含所有状态和输出采样、最终状态/输出、完整物性告警和上述计数;并非只比较曲线外观或最终值。本轮没有改变 UD00 信号语义。
|
||
|
||
## 独立 Jacobian 验证
|
||
|
||
`--verify-jacobian` 使用未缓存的 canonical 逐列差分,核对矩阵每个元素。
|
||
|
||
| 工况 | 核对矩阵数 | 不匹配数 | 与对应普通运行的数值结果 |
|
||
|---|---:|---:|---|
|
||
| 不循环,0–10 s | 896 | 0 | 完全一致 |
|
||
| 循环,0–21.7 s | 1374 | 0 | 完全一致 |
|
||
|
||
共 **2270 次矩阵核对,零差异**。核对运行的 nfev 增量分别严格等于 `896 × 132` 与 `1374 × 132`;原步数、事件、完整采样及复用计数不变。这避免把重复调用缓存路径误当作独立验证。
|
||
|
||
## 回归与验收限制
|
||
|
||
新增内核/生成器测试覆盖精确输入键、各介质参数的 1 ULP 变化、正负零、失败、冲突、容量耗尽、记录关闭、观察与缓存副作用、反向管流和活动容积。测试理想气体和氦气、热状态和多变储气;全模型 RHS/输出在所有状态逐项扰动及非有限输入下与原路径逐位对照。
|
||
|
||
新增运行时测试使用 SUNDIALS 公共类型编译生产 `cvode_solver.c`,覆盖基准重置、原始差分步长、无可选工作区、分组失败恢复、取消、故意破坏复用结果后由独立核对捕获并停用优化。
|
||
|
||
相关回归包括物性、管路、生成器、依赖排序、守恒、告警、分块存储、摩擦及 Jacobian。unittest 汇总为 **Ran 52 tests,FAILED (errors=1, skipped=1)**,已实际执行的用例通过,但不能称全量验收通过:
|
||
|
||
1. `NativeJacobianProbeTests.setUpClass`:旧固定状态样本的输入 SHA 与当前物理输入不符。当前输入为 `60ed16c71b72be4ae71ca7980f4f8cdcdf6b4c4c4c8950863c2390960b71ced4`,样本要求 `670977bef67e62d9c66e8af497bada208bd72a7301be45128d185d47282cf288`。这是基线已有问题,输入及样本均未在本轮修改,也未更新样本以绕过保护;已排除换行差异。
|
||
2. `NativeJacobianRuntimeTests`:旧测试使用 Linux SUNDIALS 7.4 私有 ABI/静态库,在 Windows 跳过。新增公共类型运行时测试在 Windows 通过,但不替代真实 Linux 验收。
|
||
|
||
当前没有可用的 Linux 容器或 WSL 运行环境,未完成 Linux 编译/运行验收;本轮也未重新执行完整 Amesim 对照或浏览器端全流程。数值一致结论限定为同平台恢复基线与方向二的前后比较。
|
||
|
||
## 复现与证据
|
||
|
||
- 比较工具:[benchmark_native_jacobian_reuse.py](../../tests/manual/benchmark_native_jacobian_reuse.py)。`prepare` 冻结对应源码构建,`run` 保存单次测量及原始数据,`report` 断言全部对比项。
|
||
- 本地证据目录:`test/jacobian-reuse-20260915/`(项目忽略的验收数据目录,不随源码提交)。
|
||
- `comparison.json`:六次正式测量、两种 UD00 工况、矩阵验证和数值一致性断言。
|
||
- `before/`、`after/`、`before-cyclic/`、`after-cyclic/`:冻结构建、输入/源文件哈希与构建清单。
|
||
- 各运行子目录:`states.bin`、`outputs.bin`、`result.json`、`measurement.json`、日志。
|
||
- `regression.log`:相关回归完整输出;`delivery-verification.json`:交付源文件与实测生成文件的一致性核对。
|
||
|
||
| 构建 | buildKey |
|
||
|---|---|
|
||
| 基线,不循环 | `80cf19d21e41cb5662f934232c7a2c5302eb7fc5b91f82da3cb23f14e3f9b885` |
|
||
| 方向二,不循环 | `7fe268c97557c3e1c5a511ea5e28cf0f0479a087031abe1a38d7007dde3c4ca0` |
|
||
| 基线,循环 | `a74d52ffe2daef7ccba5030dec75209f96d39f1bc7b47436ba5351fab08a3a92` |
|
||
| 方向二,循环 | `a50f302b77a49d1aa28a4ee305239a36e8c9281ecdc93756b729183b8f1e0a0a` |
|