修复循环信号与事件采样并接入 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 通过。
This commit is contained in:
ljz committed 2026-09-17 23:50:13 +08:00
1 parent 1aac220084
commit 7611f13208
85 files changed
+11358 -33

No files matched your search

+145
View File
@@ -0,0 +1,145 @@
# 最小 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`