Files
SystemSimulationApp/tests/manual/context_shadow_report.md
ljz 7611f13208 修复循环信号与事件采样并接入 LSTP 接触定位,补充八路验证及复用实验
相较上一版 Jacobian 确定性复用更新,本次补齐事件边界一致性、结果两侧采样及接触事件定位;保留已有物性复用和组件力学公式。

- 统一 UD00 信号求值与下一事件查询的绝对时间边界,修复循环边界浮点舍入导致的阶段错位、重复或漏报,并覆盖零时长、多阶段及长周期场景。
- 引入原生输出语义 v2:保留规则网格真实时间,补充内部时间事件和状态事件的左邻及事件后采样,按保存时间、状态和离散模式重放结果。
- 两条代码生成路径均发出 LSTP 接触描述,默认定位间隙过零及非负力模式的力截断;仅在接受事件时更新防重复记录,增加 contactEvents 诊断计数。
- 补充 MASS/LSTP 独立事件实验、八路全曲线与驱动阶段配对评估,以及 Amesim 不连续点输出对照和力差定位报告;MASS 新增释放机制仍保留为独立实验。
- 保存局部 probe、context 访问与回退、shadow replay、R288 real skip/typed replay 及阀门数值尾部诊断工具和报告;未证明净收益的实验不启用为生产默认优化。
- 更新原生运行说明和元件建模规范,补充信号边界、输出语义、接触事件和实验依赖回归测试。

验证:五组专项回归共 34 项全部通过;37 个待提交 Python 文件语法检查通过;git diff --cached --check 通过。
2026-09-17 23:50:13 +08:00

146 lines
10 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.
# 最小 context shadow replay 验证结果
## 1. Candidate 能否逐位复现 Reference
**可以,在本轮两个 operation 的已覆盖路径和严格前置条件下,1,792 次 shadow replay 全部通过,出口不一致为 0。** R288 先完成全部 896 次;同一 worker 二进制通过该阶段后,才运行 position 52 的 896 次。
参考答案始终是**同一个当前 probe 入口的独立深拷贝,真实执行原 operation 后的出口**。没有把 baseline 出口当参考。baseline 只提供本 Jacobian 内的局部语义记录,不提供用于恢复的完整 context。
| 统计 | group 6 / R288 / position 16 | group 18 / R475 / position 52 |
|---|---:|---:|
| shadow 总次数 | 896 | 896 |
| 可重放 | 896 | 896 |
| 自然轨迹 reject | 0 | 0 |
| Reference/Candidate 不一致 | 0 | 0 |
| 入口 count 不同 | 638 | 24 |
| 发生 slot relocation 的 probe | 571 | 23 |
| 重定位逻辑 slot 数量 | 1142 | 45 |
| 追加条目总数 | 1658 | 1789 |
| PT hit | 0 | 168 |
| PT miss | 1658 | 1789 |
| PH hit | 0 | 1 |
| PH miss | 0 | 167 |
| 独立后续 evaluator 返回值/dy/w/context 一致 | 896 | 896 |
| 后续 evaluator 与主仿真返回值/dy/w 一致 | 896 | 896 |
| memo 条目只读验证 | 896 | 896 |
| 未写入的 probe 数据保持不变 | 896 | 896 |
| 局部 metadata 未被 Reference/Candidate 改写 | 896 | 896 |
| Candidate 物理 native 调用 | 0 | 0 |
| 主 context/浮点环境污染 | 0 | 0 |
### 如何保证比较有意义
1. 在目标 probe 的 operation 前,深拷贝 property states、全部 pipe 槽、scalar memo 的全部 entries 和计数,分别绑定到 Reference/Candidate 私有存储。两路没有共享可写 context。
2. Reference 调用该位置的原始表达式。Candidate 只解释 baseline 捕获的 query/read/valid/allocate/write/OR/scalar-get 语义;物理 native 入口有运行时禁入检查。Reference 执行期间不能补写 Candidate 的记录。
3. Candidate 从自己的 probe 副本建立 overlay。重新扫描当前有序 entries,采用原 PT/PH 的 exact `==` 和 medium 比较语义找 first-match;用逻辑 ID 映射结果,追加使用当前 count。
4. 所有条件成功后进入无失败分支的 commit,仅按记录顺序更新实际写入字段、valid OR、count、指定 pipe 槽、memo 命中计数及显式输出;不复制 baseline context,也不覆盖 probe 未写字段。reject 前没有向 Candidate 或输出提交任何存储。
5. 逐位比较输出、所有 active property 字段、valid bits、全部 pipe 字段、memo entries/计数、warning observer、errno 和 x87/SSE 环境。私有指针按“绑定到各自当前 owner”检查;不要求两个独立 allocation 的地址相等。数值字段没有容差或近似比较。
6. 两个独立出口继续执行同一份原 evaluator 后续代码,实测返回状态、完整 dy/w、context 和 memo 计数一致;再与主仿真的真实 evaluator 返回值/dy/w 核对。主仿真仍然执行原 operation,没有采用 Candidate 输出,没有进入真实 skip 路径。
7. 两轮主仿真的状态、输出、事件及全部 896 个 132×132 Jacobian 仍与未插桩基线逐字节一致。whole-context guard 源码哈希保持一致。
operation 本身返回一个 double,没有单独的 int 成功码;报告中的 evaluator 状态来自两条后续执行路径,不是用 `isfinite(output)` 代替。
### 两个具体入口例子(Jacobian 200)
| 项目 | R288 | position 52 |
|---|---|---|
| baseline count | `12` | `75` |
| 当前 probe count | `13` | `75` |
| Reference 出口 count | `15` | `77` |
| Candidate 出口 count | `15` | `77` |
| 逻辑 slot → 当前 slot | `[[12, 13], [13, 14]]` | `[[75, 75], [76, 76]]` |
R288 保留 probe 原 slot 12,在 13、14 追加;position 52 保留 probe slot 74 的压力/温度差异,查询重新扫描后仍 miss,再在 75、76 追加。
## 2. 哪些路径已经可以 replay
| 查询路径 | R288 次数 | position 52 次数 |
|---|---:|---:|
| 近零流量,无物性查询 | 67 | 1 |
| PT miss → PT miss | 829 | 727 |
| PH miss → PT miss → PT hit → PT miss | 0 | 167 |
| PH hit → PT hit → PT miss | 0 | 1 |
以上“可 replay”指本轮相应 operation 的完整 0–10 s 轨迹,且所有 runtime guard 同时成立。PH miss 的 h 登记与 valid OR、后续对刚追加逻辑条目的 PT hit 都保留。近零流量不追加物性条目,但仍执行 pipe 的有序写入,包括 valid=0 的同值写入。
R288 的 638 次 count 差异中,67 次属于无查询/无追加路径,因此只有 571 次发生实际 slot relocation。position 52 同理,24 次 count 差异中有一次无追加。不能把 count 差异次数当作重定位次数。
## 3. 哪些情况仍必须 reject / fallback
自然轨迹中各 reject 分类均为 0。为防止“全成功但拒绝机制无效”,另在私有副本中执行下列负例,要求 reject 且整个 Candidate 与输出 sentinel 逐字节不变;这些不计入自然轨迹的 896 次。
| reject 分类 | R288 负例通过次数 | position 52 负例通过次数 |
|---|---:|---:|
| `capacity_scratch` | 2 | 3 |
| `consumed_field` | 1 | 3 |
| `existing_entry_update` | 1 | 2 |
| `first_match_relation` | 1 | 2 |
| `inputs` | 1 | 2 |
| `memo_lifetime_binding` | 1 | 2 |
| `memo_miss` | 1 | 2 |
| `memo_value` | 1 | 2 |
| `no_current_record` | 1 | 2 |
| `nonfinite_or_uncovered_branch` | 1 | 2 |
| `observer_nonnull` | 1 | 2 |
| `pipe_hit_branch` | 1 | 2 |
| `query_hit_miss_path` | 1 | 2 |
| `unknown_effect_or_schema` | 4 | 8 |
| `valid_test` | 1 | 3 |
严格拒绝边界:
- 记录不属于当前 Jacobian/operation、源代码不再匹配已验证 worker、记录溢出或未知语义事件。
- 输入改变、first-match 逻辑映射冲突、hit/miss 路径改变、已消费字段或 valid 掩码结果不一致。
- 容量不足或 scratch、非空 observer、未覆盖的已有 entry 原地更新、pipe 命中分支变化、非有限结果或未覆盖路径。
- memo owner/lifetime/recording 不符合只读约束、所需 scalar key 未命中或值不匹配。Candidate 不调用物理 fallback 来弥补 memo miss。
- 舍入模式、SSE 控制模式或所需异常状态不满足已验证条件;已记录的非零 errno 前置条件不成立。
负例包括第一次追加完成后第二次容量检查失败、末尾未知事件、末尾非有限输出,因此覆盖了 overlay 已发生大量修改后的回滚,不只是入口早退。position 52 的 PH-hit 样本还直接改变 probe 已有条目的 rho 和 MU 位,确认消费值/valid guard 生效。
Jacobian memo 的 entries 始终只读,但 Reference 的 scalar get 会增加 reuses 计数。Candidate 在 overlay 中验证同一 bit-key 查找结果,并在 commit 中重放对应计数增量。没有将 baseline 的 recording/put 副作用照搬到 probe。
验证期间发现并修复了 Windows 诊断隔离问题:该工具链的 `fesetenv` 不完整恢复 SSE 控制寄存器。负例现在保存/恢复完整 x87/SSE 环境,并验证 SSE 单独改变时会拒绝。修复前失败证据保存在 `test/context-shadow-20260917/env-restore-investigation/`;本报告仅使用修复后的同一构建全量重跑结果。
## 4. Runtime metadata 需要多少
| 当前实现 | R288 | position 52 |
|---|---:|---:|
| 单条语义事件 | 176 B | 176 B |
| 最大事件数 | 132 | 138 |
| 每条 operation 记录实际使用范围 | 2224–23344 B | 2224–24400 B |
| 每阶段为 512 个事件预留 | 90224 B | 90224 B |
记录包括:Jacobian/operation 身份、四个显式输入、出口值、query 完整 key/逻辑命中关系、实际消费的字节值与 valid 掩码、创建顺序、字段更新/OR、scalar key/value、memo 绑定及环境前置条件。**不保存 baseline 完整 property/pipe context 用于 replay。** 只保留当前 Jacobian 的一条目标 operation 记录。
事务 scratch 另需一个 156816 B 的 overlay;本诊断为入口、Reference、Candidate、回滚检查及双路后续比较共保留 7 个 context 副本、2 个 22880 B frame。它们是 shadow 验证工作内存,不能算作未来 skip 每条记录都必须长期保存的 metadata。slot 映射临时表为 256 个 int(当前 ABI 1,024 B)。
这是当前保守事件表示的实测大小,未做去重或压缩,也没有据此评价性能。
## 5. 是否具备最小真实 skip 实验的条件
**已具备针对这两个单独 operation、上述四种已验证路径的下一阶段实验条件。** 下一步必须继续保持严格 guard、事务 commit、reject 后原执行以及独立 Reference 抽查/全量对比;先对 R288 单点实验,再单独考虑 position 52。
本轮没有实现真实 skip,也没有移除或放宽 whole-context guard。结论不适用于整个 R475、全部 reuse interval、新模型、其他 native kernel、容量耗尽/observer 非空/已有 entry 原地更新等未验证分支;Linux 尚未运行本实验。双路执行和详细检查的时长不作性能证据。
## 复现与证据
依赖上一轮保留的 access worker 和未插桩 baseline 文件。准备阶段核对 access worker 源码哈希;第二阶段核对第一阶段通过的 worker 二进制 SHA-256。
```powershell
.venv-win\Scripts\python.exe tests/manual/diagnose_context_shadow.py prepare
.venv-win\Scripts\python.exe tests/manual/diagnose_context_shadow.py run --position 16
.venv-win\Scripts\python.exe tests/manual/diagnose_context_shadow.py run --position 52
.venv-win\Scripts\python.exe tests/manual/analyze_context_shadow.py
```
生成文件位于 `test/context-shadow-20260917/`:`worker/build.json`、各阶段 `shadow-trials.jsonl`、`shadow-summary.json`、`shadow-negative.jsonl`、`measurement.json`,以及汇总的 `validation.json`。若出现不一致,会输出首个不同字段和完整入口/两路 context、frame、metadata 到 `first-mismatch.json`。最终两阶段均未生成该文件。
最终 worker SHA-256:`0491872485d3d97d6b79da556ea4de53b77e6daed9100112f1e1179a6dd3d18f`。
全量主轨迹哈希(两阶段相同):
- states: `100864d208ce5cd86d4728aa9c1a343b6252b057266c8ccb7010c7fb0bc14317`
- outputs: `46fdbd10844d72e4fd23debe3439fd8eb736567f48713950b1bb5faadbdb1ff8`
- events: `4a068d192278eb91bb78782cdcc7d635deaef8dabd074ddbde3edc1d5d080b7d`
- jacobians: `74d559c39973a609884c6bc9274ce1185d23e163b33d60443108c4519fedb448`