Skip to content

Release v1.9.0: 可续训模型与引擎所有权 v2

Choose a tag to compare

@EthanPeng-2048 EthanPeng-2048 released this 18 Oct 14:07
· 50 commits to main since this release

neuralnet.cpp v1.9.0 Release Notes

发布范围:v1.8.2(3966247,2026-10-14)→ v1.9.0(2026-10-18)。
主题:可续训模型文件 v8 + 引擎所有权 v2(含 GpuBackend 泄漏修复) + 推理采样与多轮对话 + Vulkan 后端结构重整 / 扫描原语提速 + GUI、CLI 与 Windows 工程化收口。
兼容性:有破坏性变更——模型文件写版本升到 v8;CpuEngine / GpuEngine 改为工厂创建;Tensor::engine() / Tensor::engine_alive() 删除;.nnckpt 续训会拒绝显式训练配方旗标。迁移见 §6。

0. 亮点速览(TL;DR)

方向 变化 收益
断点续训(v8) .nnckpt 新增训练状态段:计数器、完整优化器状态(含 Adam t)、精度四槽、lr 曲线形状、batch/accum/max-norm/stride、数据集内容身份 重启后不是“只载权重再冷启动”,而是真正接着训练;TDR / 进程重启的 loss 与动量轨迹可连续
文件完整性 文件尾新增 [sha256 32B]["NNEND"],load_model / load_train_state 在解析参数前校验 截断或损坏的模型不再静默载入错误权重
角色语义 .nnckpt 的状态段是唯一权威;.nnmodel 走 warm start,支持 dense 与三值模型 --resume .nnmodel 成为 SFT / QAT 入口;.nnckpt 不会再把 f16 断点静默恢复成 f32
引擎所有权 v2 Tensor 只保存 8 B EngineId;计算对象持 shared_ptr<ComputeEngine>;GpuBuffer 持 backend keepalive 消除 GpuBackend 故意泄漏、check-then-use 与 buffer 晚于 backend 析构的 UAF;RV-05 正式关闭
推理可用性 top-k / top-p / 重复惩罚 / 随机种子;CLI / GUI 多轮对话;history 按整轮截断到 seq_len 生成结果可复现,终端、脚本和 GUI 都能保持多轮上下文
GPU 性能 RAPT 逐头 1/rms 收集改设备侧拼装;scan_prefix 行归属 + 4 路展开 + dk ≤ 32 窄共享变体 RAPT 3-step 配对实测 888.24 → 510.24 ms(−42.6%);scan_prefix f32/dk32 单次约 5.9×
工程化 text_train 1800+ 行拆为 config/loop/recovery/checkpoint;GUI 参数声明式表;Windows clang++/MSVC 栈与测试路径修复 训练入口可测试、GUI 参数不漂移;Windows ctest 与四编译器矩阵全绿

1. 可续训模型文件(v8)

1.1 训练状态段

.nnckpt 在模型参数与词表之后追加 role 门控状态段:

[state_len u64][TrainState kvrec][优化器状态张量条目 × N]
[sha256 32B]["NNEND" 5B]

状态段保存四类信息:

  • 计数器:global_step、epoch、epoch 内步号、当前 lr;
  • 优化器状态:Adam m/v 与 t、SGD momentum、Muon、AdamWQuant 的 f16 状态与逐行尺度;
  • 训练配方:精度 profile 四槽、weight_quant、lr 调度配方与曲线形状、batch / accum / max-norm / stride;
  • 数据集身份:.nndataset 的 sha256、tokens/docs/windows、steps_per_epoch、loss scope。

--resume 读取 .nnckpt 时,状态段是唯一权威。除保存路径、保存间隔、日志间隔、--gpu、激活卸载、--max-steps 等不改变训练配方的选项外,再显式给出形状 / 优化器 / 精度 / 计数器旗标会直接报错;需要限制本次追加跑多少步时使用 --max-steps。

数据集 path 是“位置”,内容身份才是“身份”:路径可由参数覆盖,但 sha256 或网格身份不一致会硬报错,不提供绕过开关。换数据集属于新任务,应从 .nnmodel warm start。

1.2 文件角色与三值续训

  • .nnmodel 是推理角色,参数区仍按参数级 kind 保存;三值层在盘上使用 base-3 打包形态。
  • load_model(..., WeightLoadIntent::Inference) 保持只读部署语义;WeightLoadIntent::Trainable 会在宿主侧按文件 τ 反量化成 f32 latent,供三值 SFT / QAT 继续训练。
  • 反量化使用量化器的不动点:逐行 latent 的 absmean 仍等于文件 τ,用同一 τ 重新量化可复现同一组 trit,避免 warm start 第一步就发生尺度跳变。
  • mnist_train 的 role 语义仍只接受 .nnckpt;text_train 同时接受 .nnckpt 续训与 .nnmodel warm start。

1.3 兼容性

v1.9.0 可读 v5 / v6 / v7 / v8,写出一律为 v8。v1.8.x 及更旧程序无法读取 v8 新文件;需要旧程序读取时保留原文件或继续使用旧版本二进制。

2. 引擎所有权 v2 与 GPU 生命周期

2.1 新模型

  • Tensor 不再持有引擎指针,只保存 8 B、进程内单调递增且不复用的 EngineId;Tensor 拷贝与析构不增加原子计数。
  • Layer / Model / Optimizer / ExprGraph / ExprBlock 持 std::shared_ptr<ComputeEngine>;只要借用方存活,引擎就存活。
  • CpuEngine / GpuEngine 构造函数私有,统一经 create() 返回 shared_ptr;栈上构造成为编译错误。
  • GpuBackend 提供 shared()(进程共享)与 create()(独立实例);GpuBuffer 持 backend keepalive,GPU Tensor 可安全晚于 GpuEngine 析构。
  • reduce_partial_ 改为 backend 自有的裸 VkBuffer,切断 backend → GpuTensor → GpuBuffer → backend 引用环,同时修正 backend 析构中 scratch 晚于 memory pool 释放的顺序隐患。
  • GPU f16 “先算 f32、再 cast 回 f16”回退路径的 7 个出口(gather / rearrange / transpose / im2col / col2im / matmul / batched matmul)统一在进入公共 cast 前经 adopt 补 EngineId;NN_BIND_DEBUG=1 下不再把库内中转误报为未绑定输入。

2.2 RV-05 关闭

原先 GpuBackend::instance() 用进程级 new 故意泄漏 Vulkan device / instance / pipeline / memory pool。v2 改为引用计数所有权后:

  • 最后一个强引用释放时执行 vkDeviceWaitIdle、释放延迟 buffer 与池资源、最后析构 VulkanDevice;
  • GpuBuffer 不再在析构时回查可能已死亡的全局单例;
  • layer_lifetime_test 覆盖 Tensor 晚于引擎析构、Layer / Model / Optimizer 保活、跨引擎拒绝,以及 NN_GPU_LIFETIME_FULL=1 下的完整 GPU 释放路径。

GpuBackend::instance() 保留为兼容入口,但新代码应使用 shared();生命周期契约见 ../development/08-object-lifetimes.md 与 ../development/09-engine-ownership.md。

3. 推理采样与多轮对话

  • 新增 SamplingConfig:temperature / top_k / top_p / repeat_penalty / repeat_window / seed。
  • 采样顺序固定为:重复惩罚 → 温度 → top-k → top-p → 数值稳定 softmax → 采样;默认配置与旧 temperature 路径逐位等价。
  • text_infer 新增 --top-k、--top-p、--repeat-penalty、--repeat-window、--seed。
  • 多轮 prompt 的唯一实现是 Tokenizer::chat_prompt:使用训练词表的对话标记,超 seq_len 时按“一问一答”整轮丢弃,system 块与末轮保留。
  • CLI 新增 --turn <role>:<text>、--reply-out <path>、--system <text>;--interactive 改为在进程内累积历史。无状态 --turn 协议供脚本与 GUI 每轮回传历史。
  • GUI「GPT 推理」页新增对话记录、发送多轮、清空对话与系统提示;回复经 --reply-out 临时文件取回,不再解析日志。

4. GPU 后端与性能

4.1 Vulkan 后端结构

  • GPU 存储从代数层下沉到 backend/compute_gpu_storage.hpp,切断 L1 对 Vulkan 后端的反向依赖。
  • 原语 pipeline 收敛为单一目录与布局表;融合 kernel 的 9 张并行元数据表合并为 FusedKernel。
  • descriptor set 的错误分支统一经 release_desc_set_now(),batch 模式不再双重释放。
  • backend 拆分后的结构、所有权和扩展步骤见 ../development/07-vulkan-backend-map.md。

4.2 RAPT 与扫描原语

  • RAPT 的逐头 1/rms 缓存改为设备侧 cast_into + insert_rows,消除每头一次 host 往返;3-step 配对实测 741.81 → 521.68 ms(−29.7%),to_matrix 由 768 次降为 0。
  • scan_prefix_outer 专用路径改为行归属、R 行块 shared 缓存、4 路展开,并新增 dk ≤ 32 窄共享变体;累加次序未变。
  • scan_prefix 配对 A/B:dk=32 f32 10.87–10.94 → 1.81–1.87 ms(约 5.9×)、dk=32 f16 11.86 → 3.07 ms、dk=64 f32 22.33–22.41 → 7.44–7.50 ms。
  • 两项合流的 RAPT 配对实测 888.24 → 510.24 ms(−42.6%)。
  • layer_bench 新增 scan_prefix / scan_suffix、--dk 与位级哈希 --hash;scan_bitwise_test 用 CPU 参考逐位验证 GPU 扫描 kernel。

5. DSL、训练入口、GUI 与工程化

  • Fold / DSL:fold 结构由定义方自登记;新增 dsl::compute / compute_reduce 无形状重载与形状推断,门禁 dsl_shape_infer_test。
  • 训练入口:src/text_train.cpp 由约 1830 行缩到约 396 行;解析、循环、恢复、断点分别落到 cli/text_train_{config,loop,recovery,checkpoint}.hpp,非解析模块不再调用 std::exit。断点保存失败现在会让进程以非零码退出。
  • GUI:六个训练 Tab 的参数改为声明式 Field 表,补上字段表 ↔ Controller 闭包审计;画板一笔一画布项、空帧跳过与延迟光栅化,使 2000 个 motion 事件的合成审计由 37.9 ms 降到 16.6 ms,画布项由 2058 降到 59。
  • CI / Windows:新增 MSVC Debug CPU-only job,并对齐 GitHub windows-latest 的 VS 2026 镜像(Visual Studio 18 2026 生成器);Windows clang++ 补 -Wl,/STACK:8388608,MSVC 补 /bigobj;CLI 子进程测试使用绝对路径与 cmd 安全引号;scan_bitwise_test 在 Windows 与非优化 Debug 构建按 77 skip,逐位权威锚保留在 Linux Release + GTX 850M。

6. 破坏性变更与迁移

变更 影响 迁移
模型文件写 v8 v1.9.0 可读 v5–v8;v1.8.x 不能读 v8 部署侧一起升级;需要旧程序读取时保留 v7 原文件
.nnckpt 状态段为唯一权威 续训时显式传 --f16 / --t1_58 / 形状 / 优化器 / --epochs 等会报错 从断点加载配方;本次追加时长用 --max-steps
数据集身份硬校验 换数据集后不能续接旧 .nnckpt 新任务用 .nnmodel warm start
引擎必须经工厂创建 nn::CpuEngine engine;、nn::GpuEngine engine; 编译失败 auto cpu = nn::CpuEngine::create();;GPU 用 GpuBackend::shared() + GpuEngine::create(backend)
Tensor::engine() / engine_alive() 删除 从 Tensor 反取引擎的代码编译失败 显式传入引擎;跨引擎诊断用 Tensor::engine_id()
三值 .nnmodel 可续训 默认推理载入仍是只读;训练载入会反量化成 f32 latent 训练侧传 WeightLoadIntent::Trainable;要逐位复现 warm start 时继续给原精度 profile

7. 验收基线

项 结果
Linux Release + Vulkan(GTX 850M) ctest 55/55 通过,零告警;含 scan_bitwise_test / rapt_test_f16
Linux Release + Vulkan / NN_BIND_DEBUG=1 55/55 通过(CPU-only 同口径 53/53)
Linux Debug + Vulkan 54/54 通过(scan_bitwise_test 按非优化构建 77 skip;rapt_test_f16 按既有 C11 口径排除)
Windows 102 / clang 23.1 + MSVC STL / Release / 40HX 55/55 通过;NN_BIND_DEBUG=1 同为 55/55(1 条 Windows 扫描逐位口径 skip)
Windows 102 / cl.exe 19.51 + MSVC STL / Debug CPU-only 52/52 通过(GPU 用例 skip;C11 排除)
WSL 102 / clang 24 + libc++ / CPU-only 53/53 通过(GPU 用例 77 skip)
WSL 102 / g++ 15.2 + libstdc++ / CPU-only 53/53 通过(GPU 用例 77 skip)
文档门禁 doc_align_audit.ps1、doc_inventory.ps1、gui_cli_audit.py 均可行动项 0、exit 0

端到端训练:datasets/tinystories_200mb.nndataset,GPT d_model=64 / heads=4 / layers=2 / d_ff=128 / seq_len=128 / batch=8,850M GPU,20 step:

配方 loss 起 → 止 结果
f32 8.7601 → 7.6061 健康下降,无 NaN
--f16 8.7734 → 7.5770 健康下降,无 NaN
--t1_58 8.8839 → 8.0488 健康下降,无 NaN

复现命令与更多口径见 ../todo/25-release-requirements.md §4。

8. 提交索引

主题 提交
Fold 自登记 + DSL 无形状重载 + 形状推断 c7e1d32
推理采样与 CLI 参数 ebed110
RAPT host 往返消除 / RV-15 d2b7984 / 23adc49
scan_prefix 优化 + benchmark + 逐位门禁 a28aef7 / ac58a1e / 8867d78
GUI 绘制节流 + 声明式字段表 382ef9d / 0550ec8
text_train 退出码与模块化 2a86090 / cb98b66
v8 状态段 + 优化器状态 + 训练接线 + GUI 收口 bca2bdc / 11d521f / d230675 / 1fb455e / e59a078
三值模型续训(Trainable 反量化) 6f9ca5d
多轮对话闭环 09de432
Vulkan 后端结构重整 fc10b93 / 59de9e7 / 789f2ce / aff6484 / 96198d1
引擎所有权 v2 + GpuBackend 泄漏修复 9d86156 / 02ed686 / 724d441
Windows 可移植性与发布前复验 6011b4e / f42a185 / f9e842d
Release v1.9.0 见本仓 git log

完整变更:git log v1.8.2..v1.9.0 / git diff v1.8.2..v1.9.0

9. 仍 Open

  • RV-12:Loss 直接构造 IR spec 与 FoldAnchor 的时间耦合,仍按“先设计、后动手”跟踪。
  • 实验 / 后续性能项:真 f16 长跑矩阵、RAPT GQA in-kernel、FFN ReLU² 官方对拍与 HF 权重转换器。

完整台账见 ../todo/18-roadmap.md 与 ../todo/00-code-review-remediation.md。