读者:项目开发者(本仓内部工作文档)。本分册定位见
README.md;历史归档在../history/history.md。 状态:现行。
本文是"下一步该做什么"的唯一入口:把 13 号清单(原
docs/development/13-refactor-backlog.md, 现归档于docs/history/history.md)的未完成条目与未来 6–12 个月的方向合并为一份可执行的裁定台账。 13 号文档已删除(内容全在本文与docs/history/history.md);已完成项、被否决方案与历史取舍统一归档在docs/history/history.md。 底层契约的已落地部分(统一总纲 M1–M6)见docs/internal/17-unified-tensor-engine.md。 写作纪律:只写事实与决定;行号取自实测,行号漂移后以符号名为准,未能确证的位置只给文件名、不给行号。
项目已从“包揽训练/推理的应用”转向库,公共 API 不能只围绕已知内部调用方设计;能力边界优先按
解耦、复用和可组合性规划,实施顺序再按资源分批。RL 与可组合训练基础设施已按 2026-10-23
用户裁定完成(具名输出/schema → experience/objective 组件 → 通用多模型会话/编排,
见 31 §11);f16 与训练性能优化保留为已立项 backlog,等待后续排序。
工程门禁与生态缺口继续按既有裁定处理。
| 文档 | 角色 | 何时读 |
|---|---|---|
| 本文(18) | 方向 + 未完成项裁定台账(做 / 条件触发 / 不做 + 验收口径 + 现状实测);不含执行计划 | 想知道"某件事该不该做、做到什么算完成"时 |
docs/internal/27-execution-plan.md |
执行计划(优先级象限):把本文 §3/§4/§6 与 00 号 RV 台账里当前可动手的项排成"先做哪个" | 想知道"下一个先做哪个"时(本文只给裁定,排序在那边) |
31-rl-training-primitives.md |
RL 与可组合训练基础设施(2026-10-23 架构冻结,当前主线):NamedTensorSet/输出 schema、experience/objective 组件、通用 TrainingGroupSession 与编排边界;issue #23 仅为能力下界 |
设计 RL、多输出模型、多模型 Session 或接入未知库消费者前 |
docs/internal/00-code-review-remediation.md |
2026-10-11 代码审查整改立项台账(RV-01…RV-14):外部审查发现逐条复核 + 立项(证据/方案/验收/批次) | 接手审查整改时(本文只登记"是否要做",执行细节在那边) |
docs/history/history.md「13 号清单合并归档」节 |
13 号清单(原 13 号文档,已删除)的条目原文与历史执行记录 | 只在需要追溯条目来源时 |
docs/history/history.md |
全仓唯一历史归档:演进记录 / 已修复勘误 / 被否决方案 / 性能 A/B | 查"为什么当初这么改、旧数字是多少" |
docs/internal/17-unified-tensor-engine.md |
已落地的底层总纲(M1–M6 全部实施;仅 M7 未立项) | 改 Tensor/Engine/存储前 |
docs/history/history.md「docs/development 15 · 16」归档节 |
17 的前置设计(15)与 P0 盘点(16),历史引用 | 只做证据追溯 |
- 需求是否成立:是用户/库消费者需要的公共能力,还是只服务某个已知内部调用链?
- 是否已被否决(§5 裁定表 + §7 非目标)?
- 验收口径能否复现(§8 门禁与验收基线)?
库化后,通用公共能力不要求先出现两个已知内部调用方:标准语义、可组合性、明确的扩展边界 即可构成立项理由。内部重复调用只用于决定便利 preset、默认实现和优化投入;高风险/高成本后端 或生态项仍按 §6 的触发条件执行。
17 负责"底层已经是什么样"(不变量、契约、已实施分期);本文负责"上层接下来做什么"。 凡属 17 范围内的未决点(如 M7),本文只做立项与否的裁定,实施设计回 17。
本文不承载执行计划:不写"先做哪个 / 第一步动作 / 工时与并行安排"。这些一律单独成文——
当前执行排序见 27-execution-plan.md,专项方案见
31-rl-training-primitives.md、
26-f16-speedup-plan.md、04、
../contributors/release-requirements.md 等。本文只保留三样东西:
要不要做(§5 裁定表 / §6 触发条件 / §7 非目标)、做到什么算完成(§4 各行的验收口径)、
现状实测(§2/§3)。新增内容时先判断它属于哪一类;计划类内容进 27 号,本文只加一行指针。
| 维度 | 实测 | 复现 |
|---|---|---|
include/ |
82 个 .hpp / 44681 行 |
Get-ChildItem include -Recurse -Filter *.hpp + 逐文件 Get-Content 计数 |
src/ |
90 个 .cpp / 31730 行 |
同上换 src -Filter *.cpp |
shaders/ |
22 个 .comp |
Get-ChildItem shaders -Recurse -Filter *.comp |
docs/ |
67 篇 .md(含 history/history.md 与 release-notes/) |
Get-ChildItem docs -Recurse -Filter *.md |
| 最大源文件 | expr_glsl_gen.hpp 3435 行、compute_cpu_engine.hpp 2797、compute_gpu_engine.hpp 2576、compute_engine.hpp 2228、expr_dsl.hpp 1981、gui.py 2038、rl_policy.hpp 1200、backend/compute_vk_backend.hpp 856(v1.8.1 拆 4 片段后回落)。src/text_train.cpp 已不在榜——P1-1 模块化后 1830 → 450 行(循环/恢复/断点拆到 cli/text_train_*.hpp) |
逐文件 (Get-Content $f).Count |
| ctest | 64 个注册(GPU 树,2026-10-30 实测)= 51 个测试目标(list(APPEND NN_TEST_TARGETS 计数)+ 13 个变体/附加(cnn_test_gpu、cnn_test_f16、cnn_test_f16_gpu、rapt_test_f16、rapt_test_f16_gpu、batchnorm_test_gpu、t1_58_test_gpu、bitnet_struct_test_gpu、write_epoch_test_gpu、ternary_gemm_test_gpu、adam_quant_test_gpu、fusion_custom_layer_example、expr_fuse_test);无 Vulkan 的树注册 62 条(fusion_custom_layer_example / expr_fuse_test 是 GPU 专属门禁) |
ctest --test-dir build -N |
| 引擎接口 | 52 个 virtual 方法、Layer/Loss/Optimizer 直调 32 个;L2-VIOLATIONS: 0;宿主桥 39 处(仅披露,2026-10-23 实测) |
pwsh -File bench/doc_inventory.ps1 |
| 版本 | release v1.13.0,git tag v1.13.0;CMakeLists.txt 的 project(... VERSION 1.13.0)(口径仍为 git tag 是版本权威;版本号·分支·发布治理见 33);release-notes/ 覆盖 v1.5.0 → v1.13.0 的全部 tag(含 v1.10.0-rc0 / rc0.1 两个预发布候选;历史补写记录见 release-note 索引) |
git tag --list 'v1.*' | sort -V | tail + 读 CMakeLists.txt + ls docs/release-notes/ |
| CI | .github/workflows/cmake-single-platform.yml:clang++ / Ninja / Release / NN_ENABLE_NATIVE=OFF,Linux + Windows;开 NN_ENABLE_TESTS 并跑 ctest(v3 起设备域检查默认生效,无需第二轮调试开关门禁)。另有 msvc-debug job:Windows + Visual Studio 18 2026(cl.exe)/ Debug / NN_ENABLE_GPU=OFF 纯 CPU / ctest(除已知 C11 外全跑;P1-5,2026-10-18) |
读该 workflow |
口径说明:表中行数均为总行数(实测刷新)。
64(GPU 树)/62(无 Vulkan 树)是当前唯一正确计数;--preset各树同口径(GPU 是否可用决定 两条 GPU 专属门禁是否注册)。文档中其它 ctest 计数写法属历史记录:已完成行(如 P2-3/P2-8 的 "47/47")与docs/history/history.md的旧数字是当时的验收事实,不属计数口径冲突;新增/修改文档 时写当前值。口径差异来源见 §3 工程化第 4 条。
| 底座 | 状态 | 依据 |
|---|---|---|
| 统一 Tensor / ComputeEngine 契约(M1–M6) | 全部实施 | docs/internal/17-unified-tensor-engine.md §5 |
| 访问不变量(Tensor 存储私有、一切经引擎) | 铁律 #11,编译期强制 | AGENTS.md §5 |
L2+ 计算路径禁用 Matrix |
铁律 #12,审计口径 L2-VIOLATIONS: 0 |
AGENTS.md §5;bench/doc_inventory.ps1 第 [4] 节 |
| AOT 注册表 + 单 fold 注意力 kernel(主路径 JIT 兜底) | 现行;掩码 × 位置偏置两正交维度 | docs/internal/02-operator-fusion.md |
| 位置编码多态统一(按注入点分所有权) | 现行;新增 compute_position_encoding.hpp |
docs/history/history.md「Layer 层简化轮」条 |
| BPE 保序并行 encode(任意并行度逐字节一致) | 现行 | AGENTS.md §12 |
声明式初始化 InitSpec(初值跨进程确定) |
现行 | docs/internal/17-unified-tensor-engine.md §4.4 |
| CPU/Vulkan 双后端 + 多设备选择 | 现行 | AGENTS.md §2 |
含义:本文的路线图不需要再排"底层重构"——底层已完成;缺口集中在工程门禁与上层生态。
每条 = 一句话现象 + 坐标 + 影响面。坐标只写在已实测确认的位置。
| # | 现象 | 坐标 | 影响面 |
|---|---|---|---|
| C1 | GPU stable=f16 训练 loss 回读冻结(权重照常更新) |
docs/internal/14-f16-stable-gpu-loss-frozen.md |
GPU f16 训练的 loss 曲线不可观测;无对应 ctest 用例 |
| C2 | optimizer=f16 无 loss scaling 即更新爆炸、stable=f16 约 200 步 NaN |
docs/development/05-mixed-precision.md §12.5;src/text_train.cpp 解析处只赋值不校验;核对与立项见 24-f16-training-defects.md |
用户可组合出必崩配置,且无任何启动期提示 |
| C3 | NormType::BatchNorm 静默回落到 LayerNorm |
compute_layer_mlp.hpp:782(make_norm_layer);README.md:248 声称支持;gui.py:60 把 batchnorm 列为可选项;model_spec.hpp:43 保留枚举 |
模型规格写 batchnorm、实际跑 layernorm,无告警、无日志。✅ 已解决:真正实现 BatchNorm 层(P0-3),make_norm_layer 真分支,见 docs/history/history.md |
| C4 | checkpoint(.bin)不存 Adam m/v |
model_serialization.hpp(版本常量现为 v7,见该文件注释);compute_optimizer.hpp 无 save_state/load_state |
TDR 重启 / --resume 后动量归零,续训轨迹不连续。2026-10-16 裁定:范围扩写为「训练状态段」(计数器 / 优化器状态 / 训练配方 / 数据集身份),见表下 P1-2 行 |
| C5 | .bin 无整文件校验和与尾部完整性标记 |
model_serialization.hpp 版本常量附近的注释(明示"若引入需升 MODEL_VERSION") |
截断/损坏的模型文件无法与合法文件区分 |
| C6 | gpt_test 偶发失败未定位taskset -c 0,1 2 核超订)零失败且日志逐字节一致(单一 md5)⇒ 不存在数值随机性;历史 1/62 只能是环境差异(编译器/CPU/FMA)或当次进程级异常。已加环境指纹行([env] 编译器/标准库/构建/线程数/FMA)使未来任何失败自带坐标;不加 retry/skip(输出确定 ⇒ 失败必属环境或代码变化,重试会掩盖回归) |
13 原条目 §9.5(62 次直跑 1 次失败、日志被覆盖);本轮证据与复现命令见 docs/history/history.md |
剩余风险 = ≤1.5%(95% 上界,本机口径)的 CI 偶发红;已在失败日志自描述上闭环 |
| C7 | RAPT / CNN 未接 f16:Conv2D 权重/偏置/梯度硬编码 Precision::F32 |
compute_layer_conv.hpp:148(权重)、:151(偏置)、:154/:155(权重/偏置梯度);RAPT 头内 32 处 dsl::compute* 调用未接精度实参 |
f16 只覆盖 MLP/GPT 路径,CNN/RAPT 用户得不到显存收益 |
| C8 | host_bridge_uses 计数与文档不一致(曾实测 40,13/17 记 41) |
pwsh -File bench/doc_inventory.ps1 第 [4] 节 |
✅ 已回正(2026-10-16 复测:实测 39 = §2 文档 39)——P4-2 拆掉 RAPT 逐头 host 往返后该计数由 41 回落到 39,文档已随本轮刷新;披露项,从来不是违规 |
| C9 | f16 训练降速:--f16 同窗比 f32 慢 11–17%(118.4 vs 101.0 / 107.1 ms/step),与「f16 省带宽应更快」预期相反。✅ 已兑现(2026-10-14):P2-11(编译期精度特化)+ P2-13(K 切分/细 tile 变体)后 40HX --f16 1013 vs f32 1027 ms(−1.4%)、850M(无 f16 ALU)2005 vs 2038 ms(−1.6%),峰值显存 818 → 606 MiB |
24-f16-training-defects.md §4;docs/benchmarks/2026-09-25-vulkan-vs-cuda.md、2026-10-06-vulkan-vs-torch.md;docs/history/history.md「设备侧 kernel 表按阶段归因」 |
原缺口已关闭;剩余"墙钟 − 设备 kernel ≈4.2%"归 P4-1、单算子调参归 P4-2 |
| C10 | RAPT GPU 训练比同配置 GPT 慢 ≈16×(同一命令只换 --model rapt,40HX/d128·h4·L4·ff512)。✅ 已归因(2026-10-15,850M 实测 + A/B 验证):本机 b8/seq128/d128·h4·L4·ff512 复现为 5.5×(RAPT step 741.81 ms vs GPT 134.84 ms / 3 步)。原怀疑方向被证伪(host 侧扫描派发 = 0.1–0.3% 墙钟);真因是两项独立成本:① to_matrix host 往返 = RAPT 墙钟的 75%(exclusive 573.82 ms/3 步;来源 = rms_norm_forward_ 的逐头 1/rms 收集:每 block 每 step 2 × batch×heads ≤ 64 次下载,b8/h4/L4 = 256 次/step,每次 download_vector 触发整条流水线 drain ⇒ 258 次 begin/end_batch per step)。A/B 证据:--checkpoint-every 1(forward 侧不收集 ⇒ 无下载)令 RAPT forward 659.88 → 160.77 ms(4.1×),与 GPT forward 103.19 ms 同量级。② 设备侧 scan_prefix kernel = 530.40 ms 设备时间里的 340 ms(≈113 ms/step,单次 8–10 ms @ dk=32/seq=128/BH=32)⇒ 扫的是 kernel 本身耗时,不是启动/staging 常数 |
GitHub issue #15(2026-10-01 开,唯一未进本文台账的待办,本行即其登记入口);RAPT 路径 = compute_layer_rapt.hpp + 扫描原语(docs/development/06 §扫描原语);实测证据 docs/history/history.md「C10 归因」条 |
结论:归 P4-2,两把杠杆分开做——(a) 把逐头 1/rms 缓存改成设备侧拼装(insert_rows 进 (BH,seq) 缓冲,避免 download+再 upload;注意 f16 下 dst 精度须与被消费处一致)+ 逐头循环批量化(同一循环还有 1060 次 slice_rows/step);(b) scan_prefix kernel 调参(P4-2 的逐 op 项)。 ✅ (a) 已修(2026-10-15,P4-2):逐头 1/rms 收集改设备侧拼装后同配置 step 741.81 → 521.68 ms(−29.7%)、to_matrix 768→0、begin/end_batch 774→6、忙率 69.3%→84.0%,数值逐位不变(CPU f32/f16 rapt_test 输出逐字节一致);✅ (b) 已修(2026-10-15,P4-2b):scan_prefix 专用路径改行归属 + 4 路展开 + dk ≤ 32 窄共享变体,单次 7.4–7.9 → 1.64 ms、同会话 e2e step 888.24 → 510.24 ms(−42.6%),数值逐位不变(rapt_test --gpu/--f16 --gpu stdout md5 前后相同 + 新门禁 scan_bitwise_test 61 用例 CPU↔GPU 逐位一致)。新暴露的 e2e 瓶颈:host 侧 staging 等待(copy_from 355.67/510 ms ≈66% 墙钟)。见 §4.5 P4-2 行。 |
| C11 | RAPT f16 冒烟出现 NaN(已知问题,根因未定)。用户已排查,怀疑是 GPU/设备后端自身问题;Release 下不触发只是概率,不是"Debug 专有"。2026-10-18 本机补充观测:build/p1-5-debug(clang 24 / Debug / NN_ENABLE_NATIVE=OFF / CPU-only)rapt_test --f16 的 loss 3.90206 → 2.79626(step 7)→ step 8 nan;Release 同输入(build/cpu native ON / build-rv native OFF)本轮 15 步通过(末步 ≈2.24–2.26);102 MSVC Debug CPU-only 直接跑 rapt_test --f16 3/3 通过(不是必现)。CPU-only Debug 也复现过 ⇒ 至少这个构建下还存在非 GPU 的触发路径;Release/MSVC 通过不能作为"已排除"的证据 |
src/rapt_smoke_test.cpp(经 rapt_test --f16);build/p1-5-debug/test/rapt_test --f16;102 nn-p1-5-msvc |
P1-5 的 MSVC Debug job 暂以 ctest -E "^rapt_test_f16$" 排除,避免这个已知不稳定项把编译冒烟永久染红;该排除不代表问题已解决,也不影响 P1-5 的门禁结论。根因定位后应删除排除项 |
| # | 现象 | 坐标 | 影响面 |
|---|---|---|---|
| E1 | CI 是唯一自动门禁,却只编译生产目标、不编译测试、不跑 ctest | .github/workflows/cmake-single-platform.yml(configure 无 NN_ENABLE_TESTS,无 ctest 步骤) |
所有测试结论只存在于本地;回归可在无人察觉时合入 |
| E2 | 无 install() / export,无 CMakePresets.json |
CMakeLists.txt 实测 install( 0 处;根目录无 CMakePresets.json |
嵌入路径已完成:门面目标 neuralnet::nn + NN_ENABLE_GPU/NN_BUILD_APPS 开关 + nn_enable_gpu_fusion 树外可用(见 docs/usage/05-consume-as-library.md、样例 examples/downstream/);剩余:install()/find_package(用户裁定本轮不做);CMakePresets.json 已于 2026-10-11 补上(release/dev/debug/portable/cpu/probes + build/test/workflow preset,见 CONTRIBUTING.md §1) |
| E3 | CMakeLists.txt 版本与 git tag 不一致,且缺 v1.5.1 release note |
CMakeLists.txt 的 project(...) 行(已对齐 v1.6.0);docs/release-notes/ 仍缺 v1.5.1 |
版本可读性缺失;分发产物无对应变更说明(release note 缺口仍在) |
| E4 | 文档内 ctest 计数曾自相矛盾(19 vs 20) | AGENTS.md §12 已统一为实测 21(19 目标 + cnn_test_gpu + fusion_custom_layer_example) |
已修;口径差异来源见 §2 口径说明 |
| E5 | src/text_train.cpp 1746 行、34 处 std::exitinclude/neuralnet.cpp/cli/text_train_{config,loop,recovery,checkpoint}.hpp,三模块一律返回 Result 不终止进程——std::exit 全部集中在 CLI 参数解析层(cli/text_train_config.hpp) |
原坐标(CLI 解析 + 训练循环 + TDR 恢复 + checkpoint 混杂) | 原影响面(任一改动牵动全文件)已解除;C4 的前置阻塞解除,P1-2 可直接开工 |
| E6 | 单文件多职责:compute_vk_backend.hpp 5174 行 |
该文件(fence / staging / dispatch / 算子混装) | header-only 项目里增量编译是主要开发成本 |
| E7 | README.md 与实际不符:死链 docs/history/history.md、mojibake、声称链式 add<LayerType>()、文档索引缺 13–17 |
README.md:21、:35、:63、:269、索引表(:23 起) |
新用户第一入口即误导;add<T>(args...) 是返回 Result<void> 的模板方法,无链式 API |
| E8 | bench/doc_align_audit.ps1 的 [A] 只检查反引号里的文件名,markdown 链接目标不查 |
该脚本 [A] 段正则 | ✅ 已修(2026-10-15):[A] 扩展为同时校验 markdown 链接的目标可达性(相对路径按文档所在目录解析;行内代码段先剥离,避免把示例链接误当链接);实测当场抓到 contributors/release-requirements.md 的 ../CONTRIBUTING.md 死链并一并修掉。README 的 07-zipt-algorithm.md 旧死链已在 P0-2 迭代中修 |
| E9 | 归约融合 shader 不支持"归约后逐元素后处理"形态(reduce(...) * k + c 类表达式):GPU 硬报错拒绝(契约,防静默错值),CPU 已支持 |
GpuEngine::eval_expr_reduce 的拒绝分支(错误文案即本缺口);回归锁 src/ce_fusion_test.cpp「归约+后处理 (reduce*k+c)」用例(断言 GPU 必须硬报错);机制背景 docs/history/history.md 同名条目 |
该形态只能拆两步 dispatch(先 compute_reduce 再 dsl::compute 后处理),多一次 kernel 与中间张量。支持路径(通用、非单算子):归约生成器在归约累加收尾(epilogue)后接逐元素链发射(操作对象是归约结果的广播值),随后放开 eval_expr_reduce 的末指令校验;CPU 的指令下标反向切片前置校验已是同语义,可直接对拍 |
| # | 现象 | 坐标 | 影响面 |
|---|---|---|---|
| X1 | SamplingConfig(temperature / top-k / top-p / repeat_penalty / repeat_window / seed)+ text_infer 五个开关(--top-k/--top-p/--repeat-penalty/--repeat-window/--seed)+ GUI GPT 推理 Tab 同步暴露 + 门禁 sampling_test。多轮 = Tokenizer::chat_prompt(对话标记模板 + 按整轮截断)+ --interactive(进程内累积)/ --turn+--reply-out(历史自带、一次一问)+ GUI 多轮面板(ChatSession)+ 门禁 chat_prompt_test / bench/gui_cli_audit.py [7] |
采样器在 compute_layer_base.hpp(CPU 侧 host 采样,不生成 ExprSpec);多轮 prompt 构建在 domain_tokenizer_base.hpp,CLI 在 src/text_infer.cpp,GUI 历史在 cli_controllers.py(ChatSession)+ gui.py |
闭合(2026-10-16):--interactive 此前每轮只拼当轮输入(每轮从零起算)、GUI 完全无历史;现两条路径都带完整历史,且"上下文不丢"落到可断言形式 = 第 N 轮 prompt 以第 N-1 轮为逐 token 前缀(见 §4.1 P0-5 行) |
| X2 | nn::Dataset + .nndataset/.nnvocab 统一格式 + dataset_gen/dataset_convert,text_train 只吃数据集;P2b 又补上样本层(dataset_samples.hpp:训练单位 = 样本/窗口,step 是派生量)+ 训练工厂 TextTrainer;剩 DataLoader/流式 |
src/text_train.cpp 内联数据路径;train_pkg.py / cli_controllers.py 各自处理docs/internal/19-unified-dataset.md) |
流式大语料仍不可行(TextSampleSet 仍整段物化,P2-4 后半解决) |
| X3 | 无 Python / C 绑定 | 仓库仅有 gui.py 这一 Python 入口(subprocess 调 CLI) |
生态集成只能走命令行 + 文件 |
| X4 | gui.py 六个 Tab、7 处手写 collect_args |
gui.py(def collect_args 实测 7 处) |
加 CLI 选项要手改多处,漏参风险(13 §4 的"五个 Tab / 1471-1500"坐标已过期) |
| X5 | _on_draw_move 当时不降采样);实测的拖动开销真因是逐事件新建画布项(一笔 2000 事件 = 2000 个 item)+ 逐事件 PIL 画线。现改为一笔一个 item(原地 coords 刷新)+ 空帧跳过 + 视觉刷新按帧节流(_PAINT_MS = 16)+ PIL 光栅化延迟到边界(_downsample_buffer 唯一刷新点) |
gui.py 的 StrokeTrack / _paint_live / _rasterize_pending;门禁 bench/gui_draw_logic_audit.py + bench/gui_draw_runtime_audit.py |
实测(同机合成 2000 事件):16.6 ms vs 旧写法 37.9 ms(2.3×);画布项 2058 → 59(O(事件) → O(笔数)) |
| X6 | 无"写自定义层"使用文档(文档部分已修,2026-10-11):层接入的七条契约(init_impl NVI / checkpoint_mode_ 缓存 / activation_cache / 精度 profile 用法 …)现成文于 docs/development/03-write-a-custom-layer.md(含自包含、经数值梯度检查实测通过的层模板 + 可复制 gradcheck 片段 + GPU 清单);NN_UNWRAP 是 unwrap 也已在该文与 docs/development/02-cpp-api-manual.md §1.3 说明 |
指南:docs/development/03-write-a-custom-layer.md;背景实测报告(含逐条坐标)见 docs/development/09-custom-layer-ergonomics.md(v1.7.0,库外视角) |
使用者写出"能编译但静默失效"的层(精度硬编码、offload 失效、gradcheck 全无);库内 C7(Conv2D 硬编码 F32)即同一成因;剩余缺口 = R2(Layer::init 精度自检)仍为代码项 |
| # | 现象 | 坐标 | 影响面 |
|---|---|---|---|
| M1 | 优化器共 5 个:SGD / SGDWithMomentum / Adam / AdamW / Muon;其中直接派生自 Optimizer 的是 4 个(SGD/SGDWithMomentum/Adam/Muon),AdamW 派生自 Adam |
compute_optimizer.hpp:200(SGD)、:236(SGDWithMomentum)、:294(Adam)、:434(AdamW : public Adam)、:628(Muon);工厂注册名 :723、创建分支 :745 |
缺无 m/v 状态的低显存优化器,模型规模受优化器状态限制(P2-2) |
| M2 | LRLA 仅存在于文档对比表,未实现 | docs/development/08-rapt-algorithm.md §LRLA |
线性注意力家族停在本项目基线 RLA-2/RAPT |
| M3 | begin_expr/end_expr + 图融合(P1 链 / P2 写穿多输出)+ Adam/AdamW 接线;S6 自动窗口仍未接线 |
docs/internal/03-ir-optimization.md;docs/history/history.md「IR-C 定位修正与恢复立项」「IR-C P2 收官」 |
S6 之外的"能融的必须写进单个 dsl::compute"已放宽(跨表达式经录制段融合);P4 CE online-softmax fold 已落地(通用 FoldSpec 机制,5→3 kernel/step,见 docs/history/history.md「CE online-softmax 单趟 fold(P4)」);P3 跨链批量派发已落地(#b 批量变体 + BDA 实例表 + 图内同签名分组 CAP 32):设备表读数口径 = 批量/非批量分列(用户裁定),fused@optimizer 归零、派发计入 fused_b@optimizer 行,合计 1330 → 57 calls/20 步(2.85/step ≤ 6/step);批量 vs 逐个逐字节一致(含同组混形状)、字节锚逐位不变,见 docs/history/history.md「P3 跨链批量派发」 |
| M4 | M7 存储多态未立项 | docs/internal/17-unified-tensor-engine.md §5 M7 行 |
新增第三后端仍需改 compute_tensor.hpp |
| M5 | ZiPT / AttnZip 已整体移除,代码保留在 legacy/zipt 分支 |
docs/history/history.md「ZiPT 移除」条 |
记忆压缩方向暂缺实现 |
| M6 | .nnmodel 载荷是打包形态,BitLinear 载入后进 packed_only_ 部署态,backward() 直接报错(「部署态只读」)⇒ 三值模型不能从推理模型做 SFT / QAT 续训。现在:载入意图 WeightLoadIntent::Trainable 按文件 τ 反量化成 f32 latent(量化器不动点)+ 播种量化缓存 ⇒ 首次 forward 与推理文件逐位一致、可反向、可更新;.nnmodel 的 role 门禁(P1-2 的"唯一拒绝")已删除 |
ternary_pack.hpp(latent_row_scale/dequant_row);model_serialization.hpp(param_blob_to_entry 意图分流 + load_model);compute_layer_bitlinear.hpp(TernaryLatent + aux(τ) 播种分支);cli/text_train_recovery.hpp |
缺口已关闭(见 §4.2 P1-7 行);推理侧部署只读态不变(Inference 为默认意图) |
优先级判据:P0 = 低成本高价值且不修就有实际风险;P1 = 1–2 月内的能力与健壮性; P2 = 3–6 月的结构优化;P3 = 择机(trigger 未到就不排期); P4 = 持续优化方向(底座已稳后继续加杠杆,2026-10-14 立项,见 §4.5)。 每项固定四栏:目标 / 验收口径 / 成本量级 / 依赖。
排序不在这里:§4 只写"是什么 / 做到什么算完成 / 依赖什么";先做哪个见
27-execution-plan.md(见 §1.3:计划类内容一律单独成文,本文只留指针)。
| 期 | 项数 | 项目 | 共同前置 |
|---|---|---|---|
| RL ✅ 2026-10-23 | 3 | RL-0 通用多输出协议 → RL-1 schema 化 experience 与策略目标组件 → RL-2 通用多模型会话/编排;issue #23 是能力下界,公共 API 面向未知库消费者;见 31 §11、../usage/06-reinforcement-learning.md |
无;以 f32 正确性先行,不等待 f16 / 性能项 |
| P0 | 5 | CI 真跑测试(✅)、文档一致性回正(✅ 2026-10-15)、BatchNorm 禁止静默回落(✅)、CMake install/export + presets(嵌入路径 ✅ / install 用户裁定不做)、推理采样 top-k/top-p + 多轮对话闭环(✅ 2026-10-16,两半齐,见 §4.1 P0-5 行) | 无(P0-1 是所有人的前置) |
| P1 | 8 | text_train 模块化(✅ 2026-10-16)、checkpoint 优化器状态(P1-2,✅ 2026-10-16)、危险精度组合启动期告警(细则见 24)、gpt_test flaky(✅ 2026-10-15)、CI 冒烟扩 MSVC Debug(✅ 2026-10-18)、自定义层使用文档 + 精度自检(P1-6 ✅ 2026-10-14)、三值模型续训入口(P1-7,✅ 2026-10-16)、生命周期 v3 + Session 层(P1-8,🟡 2026-10-20 立项,见 28/29) |
P0-1;P1-6 无依赖 |
| P2 | 15 | .bin 校验和(✅ 2026-10-16,随 P1-2 同批交付)、Adafactor、RAPT/CNN f16、Dataset/DataLoader、Python/C 绑定、GUI 两项、header 拆分、F16C、step 内固定 I/O 开销(P2-9)、原生 f16 算术用足(P2-10)、编译期精度特化(P2-11,已完成)、优化器 f16 批量派发(P2-12)、f16 K 切分/fine tile(P2-13)、全流程真 f16(P2-14,⏸)、标准 --f16 / PyTorch AMP(P2-15,⏸) |
P0-1;P2-7 另需 P1-5(✅ 2026-10-18);P2-6 另需 P0-5 |
| P3 | 7 | 由 §6 触发条件启动(含 CUDA、分布式)——IR-C 已落地故已移出本档(2026-10-16 计数回正:原写 8) | 各自触发条件 |
| P4 | 4 | 性能利用率 / 算子性能 / 显存开销的持续提升(⏸,待 RL 收口) + API 易用性与 Fold 表达式自动化扫描(见 §4.5;P4-2 的 C10 派生 (a)+(b) 均已完成 2026-10-15) | 各自见 §4.5 |
串行约束(不可并行推进的组合):
- P1-1 → P1-2:checkpoint 优化器状态依赖
text_train先模块化,否则恢复路径继续膨胀。 - P0-1 → P0-2:文档改动需要 CI 才能被自动验证。
- P0-1 + P1-5 → P2-7:header 拆分前必须先有编译/链接期冒烟,否则无回归网。P1-5 已完成(2026-10-18)⇒ P2-7 的前置已解锁。
- P0-5 → P2-6:GUI 字段表在采样开关定型后一次改完。
- P1-2 → P2-1:
.bin校验和与优化器状态段同属版本段改动,合并做省一次MODEL_VERSION升版。 - RL-0 → RL-1a/b → RL-1c → RL-1d → RL-2a/b:没有稳定的
OutputSchema/GradientBundle与 schema 化 experience,策略梯度无法可靠对齐;多模型角色使用通用TrainingGroupSession, 编排层使用可替换的 source/buffer/sampler/metrics/checkpoint 组件。实现可分批,但公共扩展面 在 RL-0/1 时一并冻结。
| 项目 | 目标 | 验收口径 | 成本 | 依赖 |
|---|---|---|---|---|
| P0-1 CI 真跑构建 + 测试 ✅ 已完成(2026-10-12)(最高优先) | workflow 加 -DNN_ENABLE_TESTS=ON,并在 Linux 与 Windows 各跑一轮 ctest(失败时输出完整失败日志);顺带再跑一轮 NN_BIND_DEBUG=1 ctest(RV-06 绑定门禁)。实施:.github/workflows/cmake-single-platform.yml 两个 configure 步各加 -DNN_ENABLE_TESTS=ON,Build 之后加 4 个测试步(Linux/Windows × 普通/NN_BIND_DEBUG=1,--output-on-failure);打包步补 dataset_gen/dataset_convert(8 个应用入口齐全)。前置修复:matmul_q_impl(CPU/GPU)在递归 impl 产物/静态工厂产物上进公共 cast 前未 stamp → 三值用例(t1_58_test/ternary_gemm_test/model_roles_test)在 NN_BIND_DEBUG=1 下红;补 adopt 后本机 Release+CPU NN_BIND_DEBUG=1 ctest 40/40 |
GitHub Actions 绿且日志出现全部用例;需 Vulkan 的用例按退出码 77 记 skip 而非失败 | 完成 | 无 |
| P0-2 文档一致性回正 ✅ 已完成 2026-10-15 | ① ctest 计数统一(当时实测 48〔GPU 树〕/ 46〔无 Vulkan 树〕;同日 P0-5 加 sampling_test 后为 49 / 47、P4-2b 再加 scan_bitwise_test 后为 50 / 48,口径与历史数字的处理见 §2 口径说明);② CMakeLists.txt 版本与 tag 对齐(v1.8.2);③ 补 docs/release-notes/v1.5.1.md(2026-10-15 依据 git log v1.5.0..v1.5.1 与 history 两条归档补写);④ README.md 死链/mojibake/链式 API 声明/索引(已在前一轮迭代修完)。⑤ 门禁补强(原 E8):bench/doc_align_audit.ps1 的 [A] 扩展到 markdown 链接目标,并修掉它当场抓到的 internal/25 → ../CONTRIBUTING.md 死链 |
bench/doc_align_audit.ps1 的 [A][B][D][E][F] 可行动项为 0(2026-10-15 复测:[A] 0 / [D] 0 / [E] 0 / [F] 0);文档中 ctest 计数统一写当前值(当时 48,现 49) |
小–中(纯文档 + 审计脚本一段) | P0-1(否则改动无法被自动验证) |
| P0-3 BatchNorm 禁止静默回落 ✅ 已完成(真实现路线) | 已实施:compute_layer_mlp.hpp 新增 BatchNorm 层(训练/推理双态、running 统计 EMA + extra_state 序列化、forward_recompute 抑制 EMA),make_norm_layer 真分支;scan_exprs 模型 pass 补推理态 fwd+bwd 覆盖(GPU 注册表);新增断言测试 batchnorm_test(+--gpu 变体),ctest 21 → 23,scan 结构 84 → 91(库内口径;样例收集器 93) |
构造 batchnorm 规格给出真层(可观测、不再静默降级);ctest 含 batchnorm_test;详见 docs/history/history.md「BatchNorm 落地」条 |
已完成 | 无 |
| P0-4 CMake install/export + CMakePresets ⚡ 嵌入路径已完成(用户裁定拆分) | 已实施:门面目标 neuralnet::nn(add_subdirectory + 一行 link + 一个 include 即用;C++26/线程/NN_HAS_VULKAN/SPIR-V 头/Vulkan/shader 顺序全经接口传递)、NN_ENABLE_GPU=AUTO|ON|OFF、NN_BUILD_APPS 嵌入默认 OFF、nn_enable_gpu_fusion 树外可用(NN_LIB_SOURCE_DIR/BINARY_DIR CACHE 跨作用域 + GPU 不可用时 stub 报错)、消费方编译选项(-Wno-pass-failed/-fexperimental-library//utf-8)随门面传递;样例 examples/downstream/(CPU/GPU 双路径实测通过)+ 指南 docs/usage/05-consume-as-library.md。剩余:install()/find_package(neuralnet.cpp)(用户裁定本轮不做);CMakePresets.json ✅ 已于 2026-10-11 落地(cmake --preset dev/portable/cpu/probes,历史记录见 docs/history/history.md 的 presets 条) |
嵌入口径 ✅:干净构建目录里 cmake -S examples/downstream CPU 与 GPU(NN_ENABLE_GPU=ON)两路径均编译、链接、运行通过(GPU 路径含 scan 收集 91 条 = 库内口径),fusion 树外调用可用;install 口径待剩余部分 |
已完成(嵌入)/ 小–中(剩余) | P0-1(preset 需进 CI 才不腐化) |
| P0-5 推理采样 top-k / top-p + 多轮对话闭环 ✅ 两半全完成(采样 2026-10-15 / 多轮闭环 2026-10-16) | 采样半边(已实施):nn::SamplingConfig(temperature / top_k / top_p / repeat_penalty / repeat_window / seed)落在 compute_layer_base.hpp,共用采样器按"重复惩罚 → 温度 → top-k → top-p → softmax → 采样/贪心"固定顺序;GPTModel/RAPTModel::generate 新增配置重载(旧 temperature 重载保留、语义 = 全默认);text_infer 暴露 --top-k / --top-p / --repeat-penalty / --repeat-window / --seed,GUI GPT 推理 Tab 同步;门禁 sampling_test。多轮闭环半边(2026-10-16,P0-5 尾项):① prompt 构建唯一真源 = Tokenizer::chat_prompt(domain_tokenizer_base.hpp):对话标记模板(`BOS< |
system | >…< | end_of_system |
口径说明(与本文 §4 前置清单的差异):任务书前置清单把"危险精度组合 fail-fast"列在 P0; 该项归 P1,且口径已定为仅告警(不退出、不加确认开关)——细则与验收一律见
24-f16-training-defects.md§2.3 / §5 F1。本文以裁定台账为准,不重复排期。
| 项目 | 目标 | 验收口径 | 成本 | 依赖 |
|---|---|---|---|---|
P1-1 text_train 模块化 ✅ 已完成(2026-10-16)(2026-10-15 第一刀 = 退出码语义) |
抽 train_loop / recovery / checkpoint 模块;退出码语义修正(保存失败不得成功退出) |
现有关键路径回归逐字节一致;新增恢复路径单测;std::exit 只在 CLI 参数解析层出现 |
中(1746 行文件拆解,34 处 std::exit) |
无,但它是 P1-2 的前置 —— 已完成,P1-2 已解锁。落地形态:src/text_train.cpp 1830 → 396 行(只留接线与唯一出口 main),四模块落 include/neuralnet.cpp/cli/:text_train_config.hpp(TrainConfig + --help + argv 解析 =唯一允许 std::exit 的层)、text_train_loop.hpp(epoch × step + 非阻塞 loss 回读 + 梯度累积/裁剪 + 测试评估 + --max-steps + 定期断点 + NN_NAN_TRACE/NN_MEM_STATS 探针)、text_train_recovery.hpp(--resume:角色门禁 / 按文件规格重建 / 载参)、text_train_checkpoint.hpp(.nnckpt 路径派生 + 保存记账 + 收尾退出码 + .nnmodel 产出)。三模块不终止进程:错误一律 Result 上抛,main 是唯一出口(错误 → 打印 + 退出码 1);探针中止经 abort_code = 9 回报(旧 return 9 语义不变)。验收证据(2026-10-16,clang 24 + Release + NN_ENABLE_NATIVE=OFF 的 build-rv):① 关键路径逐字节一致——21 个场景(f32 / --f16 / --model rapt / --t1_58 / --grad-log / --checkpoint-every 1 / --activation-offload / --accum-steps 2 / step_cosine / --max-norm / 单窗口多 epoch)改动前后 stdout/stderr 逐行相同(仅时间字段归一)、退出码相同、.nnmodel/.nnckpt md5 逐位相同;② 错误路径文案仅 2 处有意变更(Error: X → 推理模型保存失败: X、数据集打开错误去掉 [nn] … (expr) at file:line 噪声),角色门禁与断点失败文案逐字未变;③ 新门禁 text_train_modules_test(断点路径派生 / 角色门禁 / 断点往返参数逐位一致 / 记账与退出码 / 推理模型角色);④ ctest 49/49(无 Vulkan 树;GPU 用例 77 = skip)、doc_inventory 新增第 [6] 节门禁(三模块 + src/text_train.cpp 不得出现 std::exit/NN_EXIT/NN_UNWRAP)PASS。过程与盘点见 docs/history/history.md「P1-1(第二刀)」。 |
P1-2 .nnckpt 训练状态段 + role 语义(2026-10-16 裁定扩写,原名「checkpoint 优化器状态」;进度:第一刀〔v8 段布局 + 整文件校验和,门禁 train_state_test〕+ 第二刀〔Optimizer::save_state/load_state 全表,门禁 optimizer_state_test〕已落地;训练路径接线 = 第三刀) |
.nnckpt(role=Checkpoint)增加 role 门控的训练状态段,MODEL_VERSION 7 → 8(与 P2-1 校验和/尾部标记同批升版):① 计数器(global_step / epoch / epoch 内步号 / 当前 lr);② 优化器状态 经 Optimizer::save_state/load_state(Adam m/v + t、SGD momentum、Muon、AdamWQuant 的 f16 状态与逐行尺度);③ 训练配方(精度 profile 四槽 + weight_quant、lr 调度配方与曲线形状 total_epochs/total_steps、batch_size/accum_steps/max_norm/stride);④ 数据集身份(.nndataset 文件 sha256 + tokens/docs/windows/steps_per_epoch/loss_scope)。role 语义(冻结):Checkpoint ⇒ 除"完全不改变训练"的参数外一律禁止输入(显式给出即报错,按旗标名判定、不看值;--resume-epoch/--resume-step 同在禁列),Model ⇒ CLI 全权(--resume 放开 .nnmodel,供 SFT warm start:优化器冷启动、step 归零) |
老文件(v5/v6/v7)缺段 = 冷启动语义;save→load→save SHA256 逐字节一致;TDR 模拟重启后动量非零、t 连续、loss 轨迹连续;断点自带精度 profile ⇒ 不给 --f16/--t1_58 也能完整还原;数据集身份不匹配硬报错、无逃生阀;禁列旗标显式出现即报错(单测覆盖) |
中–大 | P1-1 ✅(已解锁);P2-1 合批。落点 = model_serialization.hpp(v8 段布局 + 尾部 sha256/完整性标记)、compute_optimizer.hpp(save_state/load_state)、cli/text_train_{loop,recovery,checkpoint}.hpp 接线、bench/doc_inventory.ps1 新增门禁、GUI 的 --resume-epoch/--resume-step 随 role 禁用 |
| P1-3 危险精度组合启动期告警 ✅ 已完成 2026-10-13 | 不单独定义——需求、口径、验收一律引用 24-f16-training-defects.md §2.3 / §5 F1(口径:仅警告,不退出、不加确认开关)。落地:include/neuralnet.cpp/cli/cli_precision_warning.hpp(nn::cli::dangerous_precision_warning)+ text_train/mnist_train 调用点 + 门禁 src/cli_precision_warning_test.cpp(单测组合矩阵 + 子进程捕获 stderr 断言退出码不变) |
见 24 号台账 F1 验收口径 | 小 | 无 |
P1-4 gpt_test flaky 定位 ✅ 已完成 2026-10-15 |
未复现(278 次直跑零失败,含 2 核超订)且同机逐字节确定 ⇒ 定性为"环境差异或进程级异常",非测试随机性。未加 retry/skip(输出确定 ⇒ 失败必对应环境或代码变化);改为加环境指纹行 + 复用 P0-1 的 --output-on-failure 日志留存。证据/统计口径/复现命令见 docs/history/history.md 的同名条目与本文 §3.1 C6 行 |
连续大样本直跑零失败 ✅;结论入 history ✅ | 小–中 | P0-1 ✅ |
| P1-5 CI 冒烟扩到 MSVC Debug + 权重变化断言 ✅ 已完成(2026-10-18) | Debug 构建冒烟;训练 N 步后断言参数确实变化(防"loss 不动"类静默失败)。落地:① .github/workflows/cmake-single-platform.yml 新增 msvc-debug job(windows-latest + Visual Studio 18 2026 生成器 = cl.exe;NN_ENABLE_GPU=OFF 纯 CPU,避开 Vulkan/glslc 变量;NN_ENABLE_TESTS=ON,cmake --build(Debug 配置)后 ctest -C Debug(C11 除外));② src/optimizer_test.cpp 新增 [4] 训练冒烟:小 MLP + Adam 跑 8 步,断言 loss 有限且下降、全参数 L1 位移 > 1e-3;同一 detect_movement() 的负例(同一快照自比)必须判为"无移动",证明断言不是恒真。该段纯 CPU f32,无 Vulkan 也不会 77 跳过;③ 本机 build/cpu(Release + CPU-only)与 build/p1-5-debug(Debug + CPU-only,全量构建共 98 个 ninja 步骤)均实测 optimizer_test ALL PASS,loss ≈3.016 → 0.1555(8 步),参数 L1 位移 41824.5;④ Debug 全量 ctest 触发既有的 C11(RAPT f16 NaN;用户已排查,怀疑设备/后端自身问题,Release 通过只是概率)⇒ CI 的 Debug 测试步暂以 -E "^rapt_test_f16$" 排除并在 C11 登记,其余用例全跑;⑤ MSVC 102 实机验证(2026-10-18,ethan@192.168.1.102,全新目录 nn-p1-5-msvc):VS 2026 18.10.4 / cl 19.51.36260.0 / CMake 4.3.3,Debug + CPU-only。首次构建 text_train.cpp 触发 C1128(补 /bigobj,目录级 + 接口选项);ctest 又触发 9 个 0xC00000FD 栈溢出(t1_58/bitnet_struct/model_roles/batchnorm/model_spec_validation/text_train_modules/train_state + 2 个 GPU 变体,MSVC 默认 1 MB 栈;补 /STACK:8388608)。修复后 CI 口径 ctest 51/51 通过 / 0 失败 / 180.00 s(rapt_test_f16 按 C11 排除,20 条 GPU/依赖 app 用例 skip;该用例在 102 MSVC Debug 上单独跑 3/3 通过,排除是为避免概率性红);另跑不排除的完整 ctest 52/52 通过 / 181.61 s(rapt_test_f16 2.33 s 通过);optimizer_test MSVC 实测 loss 2.773293 → 0.170448(8 步),参数 L1 位移 41965.2;⑥ GitHub windows-latest 已切到 VS 2026 镜像,生成器同步为 Visual Studio 18 2026 |
CI 中 MSVC Debug 目标编译通过;权重变化断言可检出冻结(含负例);C1128 已实测触发 ⇒ /bigobj 已加;栈溢出已实测 ⇒ /STACK:8388608 已加 |
中 | P0-1。复用 f16_writeback_probe 的"8 步 Adam 参数必须移动"思路,但改跑纯 CPU f32 以覆盖无 Vulkan 的 Debug job |
| P1-6 自定义层使用文档 + 精度自检(文档部分 ✅ 已完成 2026-10-11;精度自检 R2 ✅ 已完成 2026-10-14) | ① 文档:已落 docs/development/03-write-a-custom-layer.md(层骨架模板 + 可复制 gradcheck 片段 + 七条契约 + GPU checklist;示例层经数值梯度检查实测通过 `max |
num−an | = 4.7e-06、50 步 Adam 收敛)。② 代码(**已完成**):Layer::initNVI 在init_impl之后统一执行check_param_precision_()——层声明的 param槽是存储精度时,逐个校验parameters() 的张量实际存储精度与之相同(precision_bytes == 0的 T1_58 等非存储精度声明跳过)。**它当场抓到了 3 处真实静默降级**:Conv2D 的 w_/b_、RAPT 的 token_emb_、以及ReLULinearAttention**从未把 profile 转发给它自持的 4 个 Linear**(RAPT 注意力投影权重在--f16` 下一直是 f32)——前两处在 P2-3 修掉,第三处由本自检在扫描期报错后发现并修复(现 47/47 全绿) |
文档:按模板能写出可训练的自定义层;自检:硬编码 F32 的层在 init 期被拒绝 |
| P1-7 三值模型的续训入口(打包 → latent 反量化载入) ✅ 已完成(2026-10-16) | 让 --resume <x.nnmodel>(role=Model,三值层为打包形态)能进入可训练态:载入意图 WeightLoadIntent(与文件角色正交)分两路——Inference(默认)= 部署只读态、Trainable = 序列化层按文件 τ 把打包权重反量化成 f32 latent(ternary_pack.hpp 的 latent_row_scale/dequant_row,宿主侧逐行解码)+ 层按文件 τ 播种量化缓存,不再落到 packed_only_。反量化取量化器的不动点 L = trit·(τ·K/n)(n = 该行非零 trit 数):字面的 trit·τ 会让逐行 absmean 变成 τ·n/K ⇒ 续训一开始就是有效权重的尺度跳变(见「为什么不是 trit·τ」)。层协议不变:反量化后用 TernaryLatent + aux(τ) 交回 import_param,dense / .nnckpt 路径逐位不变 | 反量化载入后首次 forward 的 wq/τ 与文件内打包权重逐位一致(量化确定性:model_roles_test [6] 位级比对打包字 + τ);随后 backward 可跑、8 步 Adam 参数确实移动(同一用例 + text_train_modules_test 的三值 GPT 端到端);dense 文件两种意图参数逐位相同;逐行 absmean(latent) == τ(不动点,实测最差相对偏差 5.0e-08,ternary_gemm_test [8]) | 小–中 | ✅ 已完成 2026-10-16;前置 P1-2 的 role 语义已落地。落点 = ternary_pack.hpp(反量化 helper)、model_serialization.hpp(param_blob_to_entry 的意图分流 + load_model 新实参)、compute_layer_bitlinear.hpp(播种缓存)、cli/text_train_recovery.hpp(删 check_resume_target、改传 Trainable)、src/mnist_train.cpp。验收证据见 docs/history/history.md「P1-7」条 |
| P1-8 生命周期 v3 + Session 层 ✅ 2026-10-20 落地(v1.10.0-rc0);✅ P2b 已完成 2026-10-21(v1.10.0-rc0.1);✅ 30 号单步边界 2026-10-22 修订 | 删 Tensor 的 EngineId provenance 与 stamp_/adopt/bound/NN_BIND_DEBUG,改为"设备域从存储派生"的统一模型(CPU/host 域常量 + GPU backend 域;逐操作数对本引擎校验;import 是唯一跨域入口)。同时修审计确认的 D1–D9 生命周期缺口(D3 的 optimizer 非拥有引用通过 Session 层结构化解决)。30 号修订:Session 接收 micro-batch、内置梯度累积并按 global batch 有效单位归一化;数据集经 TextSampleSet 接入 TextTrainer,运行态 TrainState 归 Trainer | 见 28 §5/§6、29 §9、30:CPU/GPU ctest + ASan + 文档审计;新增 global/micro 等价与累积回归 | 中–大 | 30 号已落地;剩余平台矩阵按发布要求执行 |
为什么不是
trit·τ(P1-7 落地时的实现口径,2026-10-16):本项目量化器的尺度定义是 逐行 absmean(τ = (1/K)·Σ|W|),所以"把 trit 乘回 τ"得到的 latent 不在量化器的像里: 它的逐行 absmean 是τ·n/K(n = 该行非零 trit 数,≤ K)⇒ 第一次参数写回后重算 τ 就是τ·n/K,有效权重wq·τ随之缩n/K倍 —— 对 warm start 而言这是"载入后第一步就换了模型"。 取L = trit·(τ·K/n)则两条不变量同时成立:行 L1 质量 =K·τ(⇒absmean(L) == τ,与训练时 latent 的定义同源)且非零幅值τ·K/n ≥ τ > 0.5τ(⇒ 再量化复现同一组 trit)。首次 forward 与 文件逐位一致由"层按文件 τ 播种量化缓存"保证(τ与容器字都逐位来自文件,不经过重算)。
P1-2 状态(2026-10-16):✅ 四刀全部落地 —— ①v8 段布局 + 整文件校验和(含 P2-1)②
Optimizer::save_state/load_state全表 ③训练路径接线 + A/B 禁列 + 数据集身份硬错门禁 + role 语义(.nnmodelwarm start )④GUI 收口。 验收口径逐条见 §8.2 门禁 7;过程与实测见docs/history/history.md的四条「P1-2(第N刀)」;上面 P1-2 行内的"进度"字样以本条为准。
| 项目 | 目标 | 验收口径 | 成本 | 依赖 |
|---|---|---|---|---|
P2-1 .bin 整文件校验和 + 尾部完整性标记 ✅ 已完成(2026-10-16,随 P1-2 同批交付) |
尾部加 [sha256 32B][magic "NNEND"](边写边算,core_sha256.hpp 的增量 sha256_update 已就绪);MODEL_VERSION 7 → 8(与 P1-2 同一次升版)。已实施(2026-10-16):v8 尾部 [sha256 32B]["NNEND" 5B](边写边算)+ verify_model_integrity 在 load_model / load_train_state 先行校验;门禁 train_state_test [5](完好 / 翻一字节 / 截断三态)与 §8.2 门禁 7 的 ④ |
截断/损坏文件明确报错;合法文件 round-trip SHA256 一致 | 小–中 | P1-2(同一版本段改动,合并做省一次升版) |
| P2-2 Adafactor 类无 m/v 优化器 | 新增不物化二阶矩的优化器,训练更大模型 | 同任务对比 Adam 的显存下降与收敛曲线;create_optimizer 可创建 |
中 | 无 |
| P2-3 RAPT / CNN f16 接线 | ✅ 已完成 2026-10-14。① RAPT:27 处 dsl::compute* 补精度实参 p_.compute(此前全部落默认 F32);两个残差分支从硬编码 Precision::F32 改为 p_.compute(与 GPTBlock/TransformerEncoderLayer 同口径);token_emb_/grad_token_emb_ 改 p_.param;rms_norm_forward_/backward_ 的输出张量从默认 F32 改 p_.compute(否则 dst/src 精度错配 → insert_rows 断言)。② Conv2D:w_/b_/grad_w_/grad_b_ 改 p_.param,4 处 dsl::compute* 补 p_.compute。③ CnnConfig 增 precision 字段,build_cnn_model(_from_spec) 在 add 之前注入(新增可选 profile 形参)。门禁:cnn_smoke_test/rapt_smoke_test 增 --f16;ctest 新增 4 条 cnn_test_f16(_gpu) / rapt_test_f16(_gpu)(断言 loss 有限且下降、梯度无 NaN) |
f16 下 CNN/RAPT 训练健康收敛;默认 profile 的 f32 逐位不变(param/compute 默认 F32) | 中 | ✅ 已完成(ctest 47/47) |
P2-4 Dataset / DataLoader 抽象 + 流式文本(前半 Dataset 已落地 = 19 号设计阶段一~三;P2b 补上样本概念/训练工厂 = dataset_samples.hpp + text_trainer.hpp;本条只剩流式后半:DataLoader/分块迭代 for_each_chunk,不再把语料整段读进内存) |
流式加载(Dataset 格式与统一只读类见 docs/internal/19-unified-dataset.md) |
大文件训练内存曲线平稳;dataset_test 逐位一致口径回归 |
中 | 无 |
| P2-5 Python / C 绑定 | 提供稳定 C ABI 或 pybind 绑定,供生态集成 | 绑定层跑通训练/推理最小示例;ABI 报错信息可读 | 中–大 | 条件触发(§6) |
| P2-6 GUI 声明式字段表 + 绘制节流 ✅ 两侧均已完成(2026-10-15) | 已实施(绘制半边):一笔一个画布项(_paint_live 原地 coords)+ 空帧跳过 + 视觉刷新按帧节流(_PAINT_MS = 16,数据侧不节流)+ PIL 光栅化延迟到 _downsample_buffer(读缓冲唯一入口)。实测:合成 2000 motion 事件 16.6 ms vs 旧写法 37.9 ms(2.3×),画布项 2058 → 59。✅ 字段表半边已完成(2026-10-15):Field 声明式表 + 纯函数 collect_fields + ParamsMixin;6 个 Tab 全部迁移(engine→--gpu / precision_preset→--f16/--t1_58 / input_method→input 这类后处理显式保留);逐字段等价性验证:同一个 fake self 驱动 HEAD 版旧 collect_args 与新表实现,22 个场景中 17 个逐字段一致、4 个是有意收紧(fixed 调度下不再发被隐藏的 min_lr/warmup)、1 个命令行层等价;审计新增 [5] 节(表 ↔ Controller 闭包),并当场抓到 TabBase 遗留 collect_args 桩覆盖 mixin(4 个页会一个参数都不发)等 2 个真 bug |
现有 Tab 参数零遗漏(bench/gui_cli_audit.py 退出码 0,五节 ✅);拖动开销下降 ✅ |
小–中 | P0-5(采样新开关已定型 ✅) |
| P2-7 超大 header 拆分 | backend 拆 fence / staging / dispatch / 算子为独立 TU;compute_vk_backend.hpp 瘦身 |
拆分前后 build 全绿 + ctest 全绿 + CPU/GPU 字节锚逐位一致 | 中–大 | 前置 = 先补编译/链接期冒烟(P0-1 + P1-5),否则拆分无回归网 |
| P2-8 F16C 半精度转换快路径 | ✅ 已完成 2026-10-14。detail::float_to_half_bits / half_bits_to_float 增加 #if defined(__F16C__) 快路径:运行时走硬件单指令(_cvtss_sh/_cvtsh_ss,imm8 = _MM_FROUND_TO_NEAREST_INT → 与 MXCSR 无关、恒 RNE),常量求值与 NN_ENABLE_NATIVE=OFF 的可移植构建仍走软件位操作(std::is_constant_evaluated() 分流;两条路径语义同源 ⇒ constexpr 求值不受影响)。新增门禁:precision_test 增「快路径一致性」段——用 23 条 f32→f16(±0 / 次正规 / 2^-25 平局 / 65504/65519/65520/2^16 上溢边界 / ±inf / NaN 负载)与 15 条 f16→f32 位型,把编译期软件路径与运行期硬件路径逐位对比。实测:CPU GPT f16 训练 10 步 3.6 s → 1.9 s(f32 1.9 s,即 CPU f16 不再慢于 f32);NN_ENABLE_NATIVE=ON(F16C)与 OFF(portable)两态均通过;ctest 47/47 |
CPUID 探测 + 两态构建 + 逐位对拍 | 小 | ✅ 已完成 |
| P2-9 训练 step 内固定 I/O 开销归因与消除 | ❌ 已评估-不做(2026-10-14,实测推翻前提)。原判断"每步约 20% 墙钟在 copy_from ⇒ 可消除的固定开销"不成立:① host 等待总量不变、只是位置可移——把 staging ring 从 64MB×4 改成 8MB×16(消除 acquire 阻塞)后 copy_from 392 → 3 ms,但 flush_batch 同步从 955 → 1213 ms,两者之和恒 ≈1347 ms;② 设备忙率 95.9%,host 本就在等 GPU,减少等待点不缩短墙钟(改后 3 轮墙钟 2200/2059/2053,与原 2044 在噪声内,故已回退该改动);③ "减少每步帧数"方向相反——--flush-interval 1 → 4(flush 次数 105 → 20)墙钟 2044 → 2096 ms(+2.5%),因为大帧降低 host 录制与 GPU 执行的overlap(默认 1 已是实测最优,见 text_train 注释);④ 真正的天花板 = 墙钟 − 设备 kernel ≈ 86 ms/15 步 ≈ 4.2%,且 f32/f16 同幅、与精度无关。结论:该项没有可回收的收益;保留默认配置。 |
归因到具体调用点与每步 drain 次数(✅ 已完成,见左);消除后 e2e step 下降(❌ 实测无收益) | 无 | 低 |
P2-10 原生 f16 算术(shaderFloat16)用足 |
🟡 已评估-不再扩张(2026-10-14,附实测)。口径:原生 f16 允许启用、不排除——#a 在运行期查找序里优先级最高,能力经 shaderFloat16 查询 + 启用(逃生阀 NN_VULKAN_NO_16BIT_ALU),40HX 实测已有 9 条结构命中 #a。实测增益(40HX,d64/h4/L4/ff256/seq256/b64,f16,15 步 ×3 轮,NN_VULKAN_NO_16BIT_ALU=1/0 配对):ALU 开 1005 ms vs 关 1021 ms ⇒ 现有 native16 覆盖贡献 ≈1.5%。为什么不再把资格扩到 fold / matmul / reduce:① 这三类的耗时主体是归约累加循环,而累加按数值要求必须保持 f32(本仓 §7.2 与业界 fp16 GEMM 同口径)⇒ 扩资格只能覆盖其中的逐元素片段,量级与已覆盖的 9 条同构(≈1%);② 其余排除项(rparams / 微常量 / 行-列-批索引值)是原则性的——rparam 恒 f32 传递(放宽会把整链隐式提升回 f32,收益归零),微常量与索引在 f16 下会 flush/失精(放宽即静默错值);③ 因此原判断"最重的几条链永远拿不到原生 f16 ⇒ 收益大"不成立:那几条链的成本在 f32 累加循环里,不在 f16 可用片段里。保留:#a 优先级、NN_VULKAN_NO_16BIT_ALU A/B 逃生阀、单元与端到端回归全部不变(f16_precision_test / 40HX 的 #a 命中实测) |
40HX 上 --f16 step ≤ f32(✅ 已达成:1013 vs 1027);原生开更快(✅ 实测 +1.5%,但扩张收益有界 → 不做) |
26 的 S5 |
低 |
| P2-11 编译期精度特化(去运行期分派三元) | ✅ 已完成 2026-10-13。把"精度是运行期参数"(#x)在热路径换回"精度是编译期常量":新增 key#s(全输入 f16 + 输出 f16,无条件发射)与 key#xxxx(扫描期真实观察到的签名:scan_exprs 的 dry-run/模型 pass 各跑 f32+f16 两遍,scan_register + CPU 引擎 eval_expr* 按真实张量精度 + 真实 P 记入 ExprRegistry::variants);运行期查找顺序 #a → #xxxx/#s → #x(未枚举到的签名照旧兜底)。只需 16 位存储,不需要 shaderFloat16 |
850M:--f16 2260 → 2055 ms/15 步(f32 2037,+10.6% → +0.9%),峰值显存 818 → 606 MiB;ctest CPU 41/41 + GPU 43/43;构建期 110 条签名 → 88 条特化 |
无 | ✅ 已完成(26 §4 S1s、24 §4.5) |
P2-12 优化器 f16 批量派发(#b) |
✅ 已完成 2026-10-14(两段:#b 变体发射 + "scan 与运行期同源"修复)。① #b 对每个 extras 为空的静态签名变体各发一份(键形如 key#0002#b;extras 的元素类型不在 ExprPrecSig 编码里 → 带 extras 的 f16 结构仍逐 kernel 降级);运行期组键带精度身份、实例缓冲按 t.precision() 取槽位。② 残差收口:Adam 复合 kernel 在 --f16 下逐成员降级的根因是 scan 与运行期不同源(不是派发器)——(a) scan 的优化器 dry-run 把当前 pass 的 precision profile 透传给 create_optimizer(否则 f16 pass 融合出的复合结构与运行期不同 ⇒ 命中不到 ⇒ 降级);(b) scan 的 CPU end_expr 为复合 kernel 补记运行期精度签名(单节点有 scan_register/eval_expr* 入口,融合结构只在 GPU end_expr 才算出签名)。实测(40HX,f16,d64/h4/L4/ff256/seq256/b64,20 步,329f8f1 vs 5bb6a51 配对):[ir-c][degrade] 70 → 0/步;优化器派发 138.7 → 8.55 calls/步(−94%)(每步恰 3 组批量:K1 #0002#b / K2 #0002#b / 复合 #10004#b,各 32+32+6 实例);优化器 host 阶段 9.94 → 6.51 ms/步(−34%);f16 loss 轨迹与 f32 同步(850M 9.009→8.594 vs 9.006→8.591)。端到端墙钟无可见收益(1320.95 → 1324.08 ms,噪声内)——设备忙率 95.5%,host 节省被 overlap 吃掉。字节锚(cpu/40HX/AMD iGPU)逐位不变。边界:只覆盖 scan 真跑过的 profile(f32 + --f16);其它显式组合(stable=f16+optimizer=f16)仍按设计回落降级 |
f16 下优化器回落批量派发;残差收口后每步 0 降级、派发 −94%(e2e 收益在 GPU-bound 下不可测) | P2-11 | 低 |
| P2-13 f16 的 K 切分 / fine tile 变体 | ✅ 已完成 2026-10-14。把 sig 穿进 #f/#ks/#kr 生成路径:每个静态签名变体各发一份网格粒度变体(键形如 key#10003#ks);部分和缓冲恒 f32(后端按 f32 分配 → #ks 输出声明钉成 float,sig 只决定 A/B 读取类型),末段由 #kr 按 sig 落盘;后端"网格变体无需 16 位存储"的豁免收窄到纯 V0 键。实测:40HX(b64)该 wgrad f16 16.0 ms/块 vs f32 25.1 ms/块(此前 f16 79 ms/块);40HX 端到端 --f16 1013 ms vs f32 1027 ms(−1.4%),850M(b16)--f16 2005 vs f32 2038 ms(−1.6%) |
40HX 上 --f16 step ≤ f32;850M 不回归 |
中 | ✅ 已完成(24 §4.5、26 §4 S3) |
| P2-14 全流程真 f16(恢复计划) | ⏸ 已立项、暂缓执行(2026-10-23:RL 优先)。2026-10-18 恢复立项时的事实仍有效:F5 后四字段全 f16 已可训练,但还不是真 f16(CE 标量仍是 F32 补丁、matmul/归约仍有 f32 累加、native16 未全覆盖)。本项要求:B-Mem = 训练/推理/checkpoint/model 文件无 f32 持久张量;capable 设备另追 B-Arith = 零 f16↔f32 转换(补偿 kernel 的局部 f32 逐条豁免);incapable 设备转换只由计算引擎在算子内部隐式完成(Layer/DSL/CLI 零手写 cast)。包含一键 --f16-all、native16 全覆盖、f16 累加/CE 标量改造、logits/CE 融合、R2.5 数值鲁棒性技术栈(SR / GradientStabilizer / ECO / attention δ 修复,见 26 §8.B.7)、全模型/全设备长跑与转正。原 S1/S5 的“已评估-不做”只针对当时的提速目标;S1 重做前必须先让 scan_exprs 覆盖 CE backward |
见 26 §8.3 R0–R6、§8.B.7 与 §8.B.4 验收矩阵;B-Mem 必达;B-Arith = capable 设备 cast/cast_into = 0、f32 临时量 = 0(补偿 kernel 豁免表);incapable 设备转换只在引擎内;GPT/MLP/CNN/RAPT × CPU/850M/40HX 长跑无 NaN、loss 下降、权重移动 |
中–大 | F5 ✅;RAPT f16 C11(§3.1)是 R5 前置;当前等待 RL 主线收口 |
P2-15 标准 --f16 训练(参考 PyTorch AMP) |
⏸ 已立项、暂缓执行(2026-10-23:RL 优先)。A 路线目标是把现有 --f16 做成可解释、可对拍的标准混合精度——profile_f16()(f16 参数/激活 + f32 stable/optimizer)为默认,profile_master_weights()(f32 主权重 + f16 计算)为更接近 AMP 的可选形态;补动态 loss scaling(GradScaler 语义)、敏感链 f32 与 PyTorch AMP 对照。不要求零转换/native16 全覆盖 |
同数据/同 seeds:--f16 与 f32 轨迹在冻结容差内、无 NaN/冻结、权重移动;与 PyTorch AMP 同量级;loss scaling 的 growth/inf-skip/恢复用例通过;峰值显存低于 f32,step 不慢于 f32 |
中 | 无正确性依赖(原可与 P2-14 并行;A1.1 的 loss scaling 可被 P2-14 复用);当前等待 RL 主线收口 |
原生 f16 口径(2026-10-18 更新):
shaderFloat16通路允许启用、不排除——#a变体 在运行期查找序里优先级最高,设备能力经shaderFloat16查询 + 启用,逃生阀NN_VULKAN_NO_16BIT_ALU可关;40HX 实测已有 9 条结构命中#a。P2-10 的开放部分是 "把资格扩到 fold / matmul / reduce"。⚠ 口径反转(2026-10-18):旧“累加必须保持 f32” 只适用于 F4 提速路径;真 f16(P2-14 R4.1)要求 capable 设备 native16 全覆盖且零 f16↔f32 转换,P2-10 的“资格不再扩张”不再是当前结论。
2026-10-18 数值鲁棒性补充:P2-14 的口径拆成 B-Mem(硬门禁:无 f32 持久态) 与 B-Arith(capable 设备附加目标:零转换,补偿 kernel 局部 f32 逐条豁免)。SR、 GradientStabilizer、ECO、Unit Scaling、Peri-LN 与 attention
δ修复的证据/边界/落地顺序 见26§8.B.7;其中 SR/GradientStabilizer/ECO 进入 R2.5, Unit Scaling/Peri-LN 是 R5.1/R5.2 的模型级实验,不阻塞 R1–R4。
P3 不排期,只由 §6 的触发条件启动:S6 自动窗口、M7 存储多态、IR-D 第二 emitter、
ZiPT 恢复、LRLA、CUDA、分布式(7 项)。
IR-C 跨表达式图融合已不在本档——它已落地为现行能力(begin_expr/end_expr + 图融合,
已接入 Adam/AdamW),见 §3.4 M3 与 03 §7。
来源:用户 2026-10-14 指定的四条长期方向。不是新里程碑,而是"底座已稳后继续加杠杆"的常设项—— 每条都按"同窗配对 A/B + 字节锚逐位不变"验收,避免"继续提升"退化成无口径的口号。 2026-10-23 优先级裁定:本节的训练加速 / 显存性能工作暂缓,待 RL 主线收口;P4-4 的 API 工作只有与 RL 直接冲突时才调整。 与既有裁定的关系:P2-9(step 内固定 I/O)已证无可回收收益 ⇒ P4-1 不再从"搬 I/O 位置"找收益; P2-10(原生 f16 资格扩张)已评估不做 ⇒ P4-2 不含"扩 native16 覆盖"。凡与 §5/§7 冲突的做法先改裁定再实施。
| 项目 | 现状(实测锚) | 方向 | 验收口径 | 成本 | 关联 |
|---|---|---|---|---|---|
| P4-1 性能利用率继续提升 | GPU 忙率 ~95.5%(40HX f16)/ ~95.9%(850M);墙钟 − 设备 kernel ≈ 4.2%(P2-9,f32/f16 同幅、与精度无关) |
① 把剩余 4.2% 归因到 host 录制 / driver 提交 / fence 等待三处;② 提高设备端并行(帧环深度、descriptor 复用、队列提交粒度);③ CPU 线程池利用率(小算子并行度与分块) | NN_PROFILE=1 同窗配对 A/B:墙钟下降 ≥3% 且 busy% 上升;字节锚逐位不变 |
中 | P2-9(已否决的搬 I/O 不重复);core_profile.hpp |
| P4-2 算子性能继续提升 ✅ C10 派生的 (a)+(b) 均已完成(2026-10-15) | layer_bench 已提供 op 级配对 A/B(--op … + --dk/--hash)。(a) rms_norm_forward_ 逐头 1/rms 收集改设备侧拼装:step 741.81 → 521.68 ms(−29.7%)。(b) scan_prefix_outer 专用路径(dk ≤ 64)改行归属 + 4 路展开 + dk ≤ 32 窄共享变体:单次 7.4–7.9 → 1.64 ms(4.7×)、layer_bench --op scan_prefix 配对 A/B 5.9×(10.9 → 1.85 ms @ dk=32)、同会话 e2e RAPT step 888.24 → 510.24 ms(−42.6%);数值逐位不变(位级哈希 + rapt_test stdout md5 + 新门禁 scan_bitwise_test)。新瓶颈(下一手):host 侧 staging 等待 copy_from ≈66% 墙钟(与 GPU 忙时成正比 ⇒ 与 P2-9 的「host 等待总量不变」同机制)。scan_suffix_outer 刻意不改(流量/争用受限,加占用率实测更慢)。 |
按 op 逐项调参(tile / occupancy / 网格粒度)与算法(三值 GEMV、扫描原语);不含扩 native16 覆盖(P2-10 已裁定不做) | layer_bench --op <name> --hash 配对 A/B 提效、无系统性回退(噪声 ±6%);端到端不回归。(b) 已达:−42.6% 且逐位不变 |
中(shader 迭代可只重建 layer_bench ≈2 min:PCH + 1 TU;全量重建 ≈20 min 只在最后做一次) |
P2-11/P2-13;docs/internal/02;C10 归因(2026-10-15);细节/消融/否决项见 docs/history/history.md「P4-2 (b)」条 |
| P4-3 显存开销继续压低 | 04 号 L1(激活重计算)/L2(池归还)已实施;三值权重已压 param 侧(4 B → <2 B);峰值显存(850M f16)606 MiB | 立项 04 号 L3:① Adafactor 类无 m/v 优化器(= P2-2);② 注意力/softmax 子图进一步融合、消除 Q/K/V 激活集物化;③ 优化器状态低精度(AdamWQuant 已存在,4 B → 与三值同量级) |
同任务峰值显存下降,loss 曲线与基线一致(gradcheck 全绿) | 中–大 | docs/internal/04(L3 待立项);P2-2 |
| P4-4 API 易用性 + Fold 表达式自动化扫描 | ✅ ① fold 自登记已完成 2026-10-15:注意力 fold 组合改由定义方自登记(compute_layer_attention.hpp 的 attn_fold_anchor::register_all() 在静态初始化期经 FoldAnchor 登记「掩码清单 × {无偏置, 位置偏置} × {MHA, GQA}」,掩码清单 NN_ATTN_MASK_KIND_LIST 是 X 宏单一真源 → 枚举与登记表同源);expr_fold.hpp 末尾同款登记它的 3 个 v1 样例;scan_exprs.cpp 的 fold 显式登记块整体删除(消除"手写登记块漏项 = 注册表缺口"这类风险,未登记结构仍有 JIT 兜底)。实测:结构集合逐条(key + 指令摘要)与改动前零差异(126 条);-DNN_SCAN_NO_ANCHOR 下这 13 条 fold 结构全部消失(126 → 91)⇒ 自登记是唯一来源;新回归 expr_fold_test §8 锁代表值契约。② 之一 dsl::compute 无形状重载 ✅ 已完成 2026-10-15 |
剩余 ②:GUI 声明式字段表(= P2-6)、CLI/GUI/文档一致性 | ① 验收已达成:新增掩码/组合无需改 scan_exprs(NN_SCAN_DUMP_SOURCES=1 逐条来源可观测);结构数不丢(逐条对比零差异);bench/gui_cli_audit.py 退出码 0(本机实测 0) |
小–中 | docs/internal/02(fold 登记机制);P2-6 |
裁定:做。 需求来源 = GitHub issue #23;设计与验收细则唯一真源 =
31-rl-training-primitives.md。范围只含领域无关原语:
| 阶段 | 内容 | 验收口径 | 依赖 |
|---|---|---|---|
| RL-0 通用输出协议 ✅ | TensorSchema/NamedTensorSet/GradientBundle、OutputSchema、具名 forward/backward、可选 RowBandPacking、ModelSpec 输出 schema |
named API 可直接取端口;named backward 按端口分流并正确合并 trunk 梯度;packed 路径与 named 数值一致;非法 schema/布局明确报错;旧单输出文件零破坏 | 无 |
| RL-1 experience 与策略目标 ✅ | schema 化 experience、GAE/return/group transform、policy distribution、policy/value/entropy/KL components、REINFORCE/PPO/GRPO presets | 自定义字段可扩展;标准 preset 与手工组件组合数值一致;解析值/有限差分/边界/CPU-GPU smoke;只用 Loss + DSL,零新引擎原语 / shader |
RL-0 |
| RL-2 通用多模型与编排 ✅ | TrainingGroupSession;rollout source、buffer、sampler、metrics sink、可扩展 checkpoint provider |
多可训练/只读角色生命周期正确;source/buffer/checkpoint 可替换;seed 可复现;不改变 TrainingSession 归一化语义 | 公共基础(RL-0/1 定型时一并冻结) |
设计边界:issue #23 是能力下界,不是公共 API 上界。不得以 TextTrainer、
go.neuralnet.cpp 或当前内部调用方式限制 schema、objective、buffer、RNG、metrics 和 checkpoint
扩展面。实现可分批,但接口必须允许消费者绕过高层 preset、增加自定义字段与组件。
非目标(当前交付):MCTS、游戏规则、环境、自对局 worker 池(留在消费者); CUDA、分布式训练;完整动态图/自动微分框架;为 RL 新增引擎原语或 shader。
实施状态(2026-10-23):RL-0、RL-1、RL-2 全部完成;实现/门禁清单见
31 §11,使用文档见
../usage/06-reinforcement-learning.md。
f16(P2-14/P2-15)与训练性能(P4-1/P4-2/P4-3)仍按原裁定暂缓,等待后续优先级重排。
条目编号沿用 13 号原文的章节号(13 号文档已删除,原文在 docs/history/history.md)。
其原正文的归档位置:已执行/已否决记录在 docs/history/history.md「13 号清单合并归档」节;
仍未决的条目由下表承接。本节逐条覆盖其全部 16 条未决项(含 17 §5 的 M7),一条不漏。
| 条目 | 裁定 | 理由与触发条件 |
|---|---|---|
| 13 §1 线程池归约分块统一 | 不做 | 归约已是确定性分段且 1/8-worker/串行逐字节一致;剩余差异(parallel_transform/parallel_for_* 用 chunk_count(),row_reduce/col_reduce 各自行块)无正确性问题,只是概念一致性。历史上 Tensor::cpu_get_ptr 的 8-70× 教训说明动热路径风险远大于收益。归档见 docs/history/history.md |
| 13 §2 超大 header 拆分 | 做(P2-7) | 唯一被确认的日常成本是增量编译。前置:先补编译/链接期冒烟(P0-1 + P1-5),否则拆分期间 ODR/include 次序问题无网可抓 |
13 §3 text_train 模块化 |
✅ 已完成(P1-1,2026-10-16) | 原判据:src/text_train.cpp 1746 行、34 处 std::exit,CLI/训练/恢复/checkpoint 混杂;退出码语义有真实缺陷。它同时是 P1-2 的前置 —— 已拆为四个 cli/text_train_*.hpp 模块 + 396 行入口,见 §4.2 P1-1 行 |
| 13 §4 gui.py 声明式字段表 | 做(P2-6) | 实测 6 个 Tab、7 处 collect_args 手工罗列,漏参风险真实。与 §5.3 绘制节流同批做(同一文件、同一批次验收) |
| 13 §5.1 F16C 快路径 | 条件触发(P2-8) | 纯软件位操作在 f16 热点链上是真实开销,但收益未量化。触发条件(三条同时):① CPUID 探测可行;② NN_ENABLE_NATIVE ON/OFF 两态都能构建;③ f16_cpu_probe 全量对拍逐位一致。历史次正规移位 UB 教训(docs/development/05-mixed-precision.md §12.12)要求对拍先行 |
| 13 §5.2 CPU f32→f16→f32 双趟 | 不做 | 该双趟是量化模拟语义,删除会改变行为;收益是热路径一次全量转换,属低量级。若将来有真实调用方依赖"直接返回"语义,另立 API 区分而非删除 |
| 13 §5.3 GUI 绘制节流 | ✅ 已完成(2026-10-15,P2-6 绘制半边) | 原表述"每次 motion 全量降采样重绘"与实测不符(当时已在 render 端节流);真正的拖动开销 = 逐事件建画布项 + 逐事件 PIL 画线,已改为一笔一项 + 空帧跳过 + 按帧节流 + 光栅化延迟,见 §3.3 X5 与 docs/history/history.md |
| 13 §7 checkpoint 优化器状态 | 做(P1-2) | TDR 重启动量归零是真实功能缺陷(C4)。设计已明确:可选段 + 老文件缺段 = 冷启动 + MODEL_VERSION 升版。依赖 §3 先拆。2026-10-16 裁定扩写:段内容 = 计数器 + 优化器状态 + 训练配方 + 数据集身份,role 门控,v7 → v8(与 P2-1 同批);role 语义 = Checkpoint 禁 A/B 输入 / Model 全权(含 .nnmodel warm start,SFT)——细则见 §4.2 P1-2 行与 23 §2.1.1 |
| 13 §8 CI 冒烟 | 做(P1-5) | MSVC Debug + 权重变化断言可防"loss 不动"类静默失败,与 C1/C3 同族。/bigobj 未复现前不加 |
| 13 §9.4 max_abs_diff 统一 | 不做(择机) | 实测 7 份定义(attn_consistency_test.cpp、ce_fusion_test.cpp、conv2d_gradcheck.cpp、fused_gpu_test.cpp、gpu_test(已迁新仓库 compute.neuralnet.cpp tests/)、maxpool_gradcheck.cpp、tensor_expr_test.cpp),且语义有分叉(conv2d 版多形状守卫返回 1e9)。计数三处不一致:13 号原文写 9 份、src/test_common.hpp:19 注释仍写 9 份、中途交接口径写 8 份,实测为 7 份——P0-2 文档回正时需一并订正。纯测试卫生、无产品风险,机械改写有反例 |
13 §9.5 gpt_test 偶发失败 |
做(P1-4) | 偶发红在 CI 化(P0-1)后必然变成噪声;先复现再定性。62 次直跑 1 次失败、日志被覆盖,需先补日志留存 |
| 13 §9b H3 解码循环骨架 | 不做 | 仅采样段已合并,三个 generate() 循环体因运行态不同而保留;统一会引入条件分支,收益低。理由已归档 |
| 13 §9b H4 精度/形状三元组收敛 | 不做 | 尾部 p_.compute 实参在各点可能是刻意不同(RAPT 残差相加即反例),机械改写有语义风险;收益只是少写一个参数 |
| 13 §9b H5 掩码/索引构造 | 不做 | 注意力侧已随策略类收敛;剩余(conv 置换、patch 提取)的"CPU 循环 + upload_span"声明式化无正确性问题,且新原语成本高 |
| 13 §10 句柄指针化 / 存储多态提案 | 不做(已被 17 吸收) | 13 §10.8 的"不采用句柄指针化"由 17 §3 D2 维持否决;其"直接读写"诉求由访问不变量(铁律 #11)承接。存储多态部分改期 M7 |
17 §5 M7 存储多态 + as_cpu/as_gpu |
条件触发(P3) | 触发条件:第三后端出现。在此之前收益只剩"新增后端不改 compute_tensor.hpp",无调用方 |
原则:触发器不到,不写代码、不排期。触发条件必须可观测、可复现。
| 项 | 精确触发条件 | 立项时先读 |
|---|---|---|
不再是触发项:begin_expr/end_expr 图融合(P1 链 / P2 写穿多输出)已接入 Adam/AdamW step,§3.4 M3 |
docs/internal/03-ir-optimization.md §5.3、§7;expr_graph.hpp |
|
| S6 自动窗口(跨 kernel 自动融合) | 同 IR-C 的调用方判据;当前"能融的直接写成单个 dsl::compute"已覆盖生产路径 |
docs/internal/02-operator-fusion.md |
| M7 存储多态 | 第三后端出现(CPU/Vulkan 之外的引擎要落地) | docs/internal/17-unified-tensor-engine.md §4.2 + §5 M7 |
| IR-D 第二 emitter | 需要 glsl 之外的代码生成后端,且该后端必须走 AOT 注册表(表达式结构须被 scan_exprs 覆盖) |
docs/internal/03-ir-optimization.md 阶段 D;expr_emitter.hpp |
| ZiPT 恢复 | ① 压缩向量保证因果(压缩器只能看当前位置之前);② 实现质量对齐 RAPT/GPT(forward_recompute 梯度检查点 + activation offload + CLI/序列化/测试齐备);③ 有同参对比数据 |
docs/history/history.md「ZiPT 移除」条;legacy/zipt 分支 |
| LRLA | 先有与 RLA-2 / RAPT 的同参对比数据(质量、显存、吞吐),再决定是否实现 | docs/development/08-rapt-algorithm.md |
| Adafactor 类优化器 | 已排 P2-2;条件 = 需要训练超出 Adam m/v 显存预算的模型 | 本文 §4.3;compute_optimizer.hpp |
| CUDA 后端 | P3。当前明确不支持(见 §7);触发 = 目标平台出现真实需求 + 有维护者承诺长期维护 + 愿意补 IR-D 第二 emitter 的 AOT 全链 | AGENTS.md §2;本文 §7 |
| 分布式训练 | P3。触发 = 单机单卡能力被真实任务触顶,且有明确的多机部署场景 | 本文 §7 |
| 非目标 | 理由 |
|---|---|
| CUDA 全链 | 项目契约是 CPU / Vulkan 双后端,CLI 无 CUDA 参数;引入 CUDA 等于重走一遍 import / 存储多态 / IR-D 全链。仓库中无 CUDA 代码(grep 仅有 Muon 的 URL 注释) |
| 分布式训练 | 数据并行/张量并行需要先有通信层与容错语义;当前连 CI 都不跑测试(E1),先补门禁 |
| HTTP 服务化 | 仓库无任何 HTTP/gRPC 代码;推理入口是 CLI + GUI,服务化的部署/鉴权/并发语义无真实需求方 |
| ONNX 导入导出 | 无 ONNX 依赖与实现;导出需先把动态形状/精度语义固定下来,而 M7 尚未立项 |
列入本表的前提是"当前不做"有证据支持(上表逐条给了证据)。触发条件成熟时经 §6 重新立项。
| 基线 | 口径 | 当前值 / 复现 |
|---|---|---|
| build | 全绿、零告警(-Werror) |
cmake -B build -G Ninja -DNN_ENABLE_TESTS=ON && cmake --build build |
| ctest | 实测 64(51 目标 + 13 变体/附加;无 Vulkan 树 62);需 Vulkan 用例退出码 77 = skip | ctest --test-dir build |
| L2 分层审计 | L2-VIOLATIONS: 0(宿主桥用量只披露) |
pwsh -File bench/doc_inventory.ps1 第 [4] 节(实测:virtual 52 / host_bridge 39) |
| CPU 字节锚 | --steps 20 hash = 6f8849f14da23110 |
逐位一致 |
| GPU 字节锚 | dev2 hash = 8ef51b2927253c50 |
逐位一致(GPU 档位按 17 §6 容差规则) |
| scan 产物 | fused_registry.hpp(唯一产物;expr_specs.bin 已随构建期单步删除) |
tools/scan_exprs.cpp + tools/fused_generate.hpp 产物 |
| 初值锚 | gpu_stability_probe --init-hash 各模型跨进程一致 |
见 AGENTS.md §12 当前锚 |
| 文档对齐 | python scripts/doc_audit.py:A–H 八类可行动项为 0(全绿) |
实测:全绿(历史归档提及按白名单跳过) |
| 行为回归 | layer_bench 同窗交错 + 配对 A/B,无系统性回退(噪声 ±6%) |
build/layer_bench |
-
CI 必须执行 ctest:日志需出现当前全部用例(64,无 Vulkan 树 62,真源 = §2 ctest 行);77 = skip 不算失败(P0-1)。
-
开发文档不得出现 ctest 计数的旧写法:统一写实测当前值(真源 = §2 ctest 行与口径说明;2026-10-30 = 64〔GPU 树〕/ 62〔无 Vulkan 树〕)——已完成行与 history 归档里的旧数字是当时记录,不算冲突(P0-2 ✅)。
-
BatchNorm 行为门禁:构造 batchnorm 规格必须有可观测结果(报错或正确层),不允许静默降级(P0-3)。✅ 已满足:真层 +
batchnorm_test工厂断言。 -
危险精度组合:启动期告警(仅警告、不失败、不改退出码)——口径与细则见
24-f16-training-defects.md§2.3 / §5 F1(P1-3)。 -
审计覆盖补强:文档审计(
python scripts/doc_audit.py)覆盖 markdown 链接目标可达性;新增死链会在审计里以 [A] 计数非 0 暴露。 -
text_train模块不得终止进程(P1-1,2026-10-16 起生效):pwsh -File bench/doc_inventory.ps1第 [6] 节 断言cli/text_train_{loop,recovery,checkpoint}.hpp与src/text_train.cpp里不出现std::exit/NN_EXIT/NN_UNWRAP(这三种写法都会直接终止进程)——三模块的错误一律经Result上抛,进程唯一出口是main(CLI 参数解析层是另一个例外,见cli/text_train_config.hpp)。P1-2 的 checkpoint 状态段与--resume接线必须保持这条不变量:新增错误检查用NN_TRY/NN_TRY_MSG/NN_FAIL。 -
.nnckpt训练状态段与 role 语义(P1-2,v8,2026-10-16 起生效):①role = Checkpoint恢复时, A/B 类旗标(形状/配方/计数器,清单见 §4.2 P1-2 行)显式出现即报错——按旗标名判定、不看值;role = Model时 CLI 全权;② 状态段 save→load→save 逐字节一致,老版本(v5/v6/v7)缺段回落 冷启动语义;③ 数据集身份(sha256 + 网格三元组)不匹配硬报错且不得提供逃生阀;④ P2-1 的校验和 / 尾部完整性标记缺失或截断必须报错。 状态(2026-10-16):① ② ③ ④ 全部落地并有门禁——①③ 见text_train_modules_test[6] 与 端到端四例(docs/history/history.md「P1-2(第三刀)」)、② 见train_state_test[9]、 ④ 见train_state_test[5];优化器侧见optimizer_state_test(重启续跑 = 直跑逐位一致)。 已收口(2026-10-16 第四刀):gui.py按文件头的 role 字节识别.nnckpt(model_file_role), 断点续训模式下collect_args不发任何禁列键(并显示一行模式提示),.nnmodelwarm start 仍 CLI 全权;bench/gui_cli_audit.py新增 [6] 节(禁列集合 ↔kForbiddenResumeFlags逐项一致 + 两种 role 下的 收集行为 + C 类不被误砍)。 -
三值模型可续训(P1-7,2026-10-16 起生效):训练侧路径(
text_train/mnist_train的--resume)载入参数一律走WeightLoadIntent::Trainable;三值.nnmodel的打包载荷必须被 反量化成可训练 latent(不得落进packed_only_部署态),且首次 forward 的wq/τ与文件里的 打包权重逐位一致(层用文件 τ 播种量化缓存)。门禁:model_roles_test[6](打包字 + τ 位级比对、 首次 forward 逐位一致、absmean(latent) == τ、8 步 Adam 后 latent 移动、dense 两种意图逐位相同)、ternary_gemm_test[8](反量化 helper 的三条不变量)、text_train_modules_test(三值 GPT 走通resume_text_train+ 8 步 Adam,首次 forward 与文件逐位一致)。推理侧默认意图Inference不变(部署只读态 = 0.25 B/权重)。 -
多轮对话上下文不丢(P0-5 尾项,2026-10-16 起生效):多轮 prompt 的构建只有一条路 (
Tokenizer::chat_prompt),且必须满足两条可断言的不变量:① 第 N 轮的 prompt 以第 N-1 轮 的 prompt 为逐 token 前缀("上下文不丢"的可验证形式);② 超seq_len时按整轮(一问一答) 丢弃 —— system 块与末轮恒保留、丢弃后仍以 user 起头(标记结构不破),且丢弃轮数可观测。--turn的形状不合法(role 写错 / 不交替 / 末条不是 user / 与--prompt·--interactive并用) 解析期报错,不得静默降级;GUI/脚本侧一律经--turn(整段历史随采样参数一起传回)+--reply-out(回复落盘),不得靠解析 CLI 日志取回复。门禁:chat_prompt_test(库级 5 节 + 真实text_infer子进程端到端 + 7 条负例;app 缺失时 77 = skip)、bench/gui_cli_audit.py第 [7] 节(Python 侧 参数面:前缀不变式 / 回复闭环 / 清空归零 /_on_send真的传历史)。 -
MSVC Debug 冒烟 + 权重变化(P1-5,2026-10-18 起生效):CI 的
msvc-debugjob 必须 用 cl.exe + Debug 编译全部目标(NN_ENABLE_GPU=OFF纯 CPU,NN_ENABLE_TESTS=ON) 并跑 ctest(除下述已知 C11 排除项外全跑);optimizer_test的 [4] 段必须断言 8 步 Adam 后全参数 L1 位移 > 1e-3 (loss 有限且下降),并用"同一快照自比 → 判为无移动"的负例证明检测器可识别冻结。 该断言不得放在f16_writeback_probe之类无 Vulkan 就 77 的用例里——它必须在 MSVC Debug CPU-only 树上真实执行。C1128 已在 102 实测触发(text_train.cpp)⇒/bigobj已加进 MSVC 目录级与接口选项;栈溢出也已实测(9 个用例0xC00000FD, MSVC 默认 1 MB 栈)⇒/STACK:8388608已加。MSVC 102(VS 2026 / cl 19.51) Debug CPU-only 修复后 51/51 通过(180 s)。 已知排除:rapt_test_f16是既有 C11(RAPT f16 NaN,用户已排查,怀疑设备/后端 自身问题;Release 通过只是概率),CI 冒烟暂以-E "^rapt_test_f16$"排除;大版本发布 清单(25§1)仍要求 Debug 完整 ctest 全绿,C11 修复后必须删掉该排除项。
- 计划内字节变化:按 17 §6 例外流程先立新锚,新锚两次独立运行之间仍须逐字节,并在该期验收中显式记录。
- 既有故障不混入验收:C1(GPU
stable=f16loss 冻结)与 C6(gpt_testflaky)在修复前按"既有状态如实记录"处理,不得当成新回归。 - 裁定不可静默偏离:任何与本文 §5/§7 不一致的做法,先在本文改裁定并说明理由,再实施。
- 状态只写现在式:做完一项就把该项从 §4 移到
docs/history/history.md,并在 §4 留一行"已完成"指针。 - 数字必须带复现命令:任何计数(行数、测试数、锚值)都要能在命令里复现;不可复现的只写"约"或删。
- 行号会腐烂:行号只作入口线索;引用时优先给文件名 + 符号名,行号在改动后由
python scripts/doc_audit.py兜底 不覆盖的,由自动化测试兜底(新增断言测试优于文档数字)。 - 裁定要留反例:凡"不做"必须写清触发条件或反例(如 H4 的 RAPT 残差相加),否则后人无法判断能否重新立项。
- 与 13 的关系已终结:13 号文档已删除(内容全在本文与
docs/history/history.md),新增条目只进本文。 - 计划不落本文(2026-10-15 起):本文只写裁定 / 验收口径 / 现状实测;"先做哪个、第一步动作、
并行与工时安排"一律单独成文(当前 =
27-execution-plan.md),本文只留指针(§1.3)。 判断口径:可被"做/不做"二值化的进本文,只描述顺序与动作的进 27 号。
大版本升级(1.x.y → 1.(x+1).0,次版本号 +1、修订号归零)在常规门禁之上还要走一遍
../contributors/release-requirements.md 的必做清单:① 端到端模型训练测试
(这类测试不进默认 ctest,太费时);② 发布文档;③ 完整 ctest + Debug 构建;
④ 多编译器 × 标准库(≥4 组)全新构建 + ctest。小 / 修订号升级不强制。
13 号清单的"仍然生效的工程教训"中,以下 2 条在 13 删除后无处落地,按原义承接。
(其余 3 条已由别处覆盖:dsl::compute 无形状重载(已完成)见 AGENTS.md §7;max_abs_diff 计数已入本文 §5 裁定表;
gpt_test 偶发失败已列为本文 P1-4。)
否则 GPU 注册表运行期 miss(主路径 JIT 兜底)。低成本做法 = 把新表达式写成与已扫描表达式同构
(如 RAPT 除法的 ε 位置对齐 forward),即可零成本复用键。
(对应铁律 #7:AOT 注册表为预热加速;主路径未命中运行期 JIT 兜底,NN_STRICT_CLOSED_WORLD=1 恢复硬报错。)
pragma once 之下 #undef 会让后续子文件失去宏定义。测试用「#define main test_xxx + #include 子测试.cpp」
聚合编译,聚合器里任何 #undef 都会影响其后被 include 的所有子测试。