Skip to content

neuralnet.cpp v1.12.0

Choose a tag to compare

@EthanPeng-2048 EthanPeng-2048 released this 23 Oct 16:30
· 13 commits to main since this release

neuralnet.cpp v1.12.0 Release Notes

发布范围:v1.11.0(tag v1.11.0,2026-10-23)→ v1.12.0(tag v1.12.0)。
主题:RL 与可组合训练基础设施——具名多输出模型、schema 化 experience、
GAE/return/group normalization、REINFORCE/PPO/GRPO objectives、多模型角色容器与
可替换 rollout pipeline。
兼容性:无破坏性 API 或 CLI 变更。模型/断点文件格式仍为 v8;新增的
output_schema / output_packing 是 ModelSpec 可选键,旧文件缺键时保持单输出语义。
授权条款变更:项目许可证从 MIT 切换为 LGPL-3.0,升级、链接或分发前请阅读 §4。


1. 主题与定位

v1.12.0 把此前散落在调用方的 policy-gradient 公共语义收进库层,同时保留算法和
环境边界:

  • 库提供 schema、experience、objective、session 与 pipeline;
  • 环境 reset/step、MCTS、棋规、自对局 worker、replay policy 仍由消费者实现;
  • 首版分布为 categorical,其他分布经 PolicyDistribution 扩展;
  • 不新增引擎原语或 shader;RL 数值路径全部由现有 Tensor/Engine/DSL 组合。

设计背景与能力下界见 ../todo/31-rl-training-primitives.md,
调用指南见 ../usage/06-reinforcement-learning.md。

2. 新增能力

2.1 有序 schema 与具名多输出

  • TensorSchema / FieldHandle / NamedTensorSet / GradientBundle 提供稳定字段顺序、
    shape / precision / placement 校验和 setup 期名称解析。
  • Layer::output_schema()、forward_named()、backward_named() 为单输出层提供默认适配;
    OutputBundleLayer 将同一输入 fan-out 到具名分支并汇总输入梯度。
  • Model::forward_named() / backward_named() 让共享 trunk 的中间层继续使用单 Tensor,
    最后一层可展开为多端口。
  • RowBandPacking 只作为旧单 Tensor ABI 的显式兼容适配器;named API 不依赖行号约定。
  • ModelSpec 可持久化可选 output_schema / output_packing,缺键保持旧单输出行为。

2.2 Experience、GAE 与归一化

  • TensorRecord / ExperienceSchema / PolicyBatchView:标准字段可选项可按算法收紧,
    自定义字段仍可由 consumer 通过 typed record 读取。
  • GaeAdvantage:支持 done 截断、mask、terminal bootstrap;mask 外时间步不参与状态值
    或 advantage 的跨步传递。
  • MonteCarloReturn、MaskedNormalizer、GroupAdvantage:支持总体标准差、零方差与
    GRPO 连续 group span。

2.3 Policy 与 objective 组件

  • PolicyDistribution 接口与首版 CategoricalDistribution:log-prob、entropy、sample、
    analytic gradient。
  • 低层组件:ReinforceObjective、ValueRegressionObjective、
    EntropyBonusObjective、SampledKlObjective、ClippedPolicyObjective、
    ClippedValueObjective。
  • 标准 preset:PpoObjective 与 GrpoObjective;preset 的组合损失/梯度与手工组件组合
    等价。

2.4 多模型与 rollout 编排

  • TrainingGroupSession:具名 trainable/readonly role,共享同一 ComputeEngine,
    保持每个 TrainingSession 的 optimizer-before-model 生命周期。
  • RLTrainingPipeline:固定 rollout → buffer → sample → update 顺序,batch 索引、
    hooks、metrics、RNG/update/rollout 计数和 checkpoint provider 可替换。
  • TrainingSession::train_named_step:与 train_step 共用 global/micro batch 累积、
    归一化、裁剪和 optimizer update 语义,仅把最后反向替换为 backward_named。

3. 发布审查修正

独立 Release 审查在合并前修复了以下路径,并加入回归:

  1. PPO off-policy 梯度:负 advantage 的裁剪两侧及容差带内部曾使用错误分支;现在
    统一使用 ratio * advantage 的未被裁剪侧梯度,并覆盖负 advantage 的有限差分。
  2. GAE mask 语义:mask 外时间步的 value 不再泄漏到前一步 bootstrap;新增非零 value
    的 masked-value 回归。
  3. Policy batch 形状校验:REINFORCE/entropy/KL/PPO 在进入引擎前置检查 (1,T),
    阻止宽度不符时继续读写。
  4. 具名反向状态:失败的 forward 会立即失效旧的 backward 配对状态。
  5. 不可信 schema 解码:字段/名称计数在大分配前按上限和负载长度校验;字段名校验
    改为线性重复检测,schema 指纹加入字符串长度边界。
  6. Pipeline 状态提交:模型 update 成功后,即使 post-update hook 失败,也会提交
    update 计数与 on-policy buffer 清理,避免重试重复更新。

4. 兼容性与迁移

项目 v1.11.0 → v1.12.0
已有 Model/Layer/Loss/Optimizer API 不变;新增具名入口均为默认适配
已有单输出 Model::forward/backward 不变
多输出旧 ABI 使用 RowBandPacking;named API 直接用 forward_named/backward_named
模型/断点格式 v8 不变
ModelSpec 新增可选 output_schema / output_packing;旧文件缺键 = 单输出
CLI / GUI 无新增或破坏性参数
nn.hpp 聚合新增 RL 头;需要最短依赖时可改 include rl.hpp
项目许可证 MIT → LGPL-3.0;修改本库并分发时须继续使用 LGPL-3.0,应用链接本库的边界按 LGPL §4 处理

迁移旧 policy/value 双头模型时,将原有拼接输出拆为具名分支,并用
TensorSchema::create 固定端口顺序、shape 和 precision;只有仍消费单 Tensor 的调用方
才需要 RowBandPacking。

5. 验收基线

口径:NN_ENABLE_NATIVE=OFF 可移植基线;GPU = NVIDIA CMP 40HX / Vulkan SDK
1.4.350 / 驱动 616.92
。全部构建目录均为全新构建。逐项记录见
../todo/25-release-requirements.md §9。

# 配置 构建 完整测试
1 Windows clang 23.1 + MSVC STL / Release / Vulkan 239/239 步 69/69:68 pass + 1 skip + 0 fail(604.58 s;skip=scan_bitwise_test 平台口径)
2 Windows clang 23.1 + MSVC STL / Debug / Vulkan 239/239 步 69/69:68 pass + 1 skip + 0 fail(883.82 s;skip=scan_bitwise_test;rapt_test_f16 实际执行并 Passed)
3 Windows cl.exe 19.51 + MSVC STL / Debug / CPU-only 全目标成功链接 67/67:46 pass + 21 skip + 0 fail(194.66 s)
4 WSL g++ 15.2 + libstdc++ / Release / CPU-only 132/132 步 67/67:48 pass + 19 skip + 0 fail(41.05 s)
5 WSL clang 24.0 + libc++ / Release / CPU-only 132/132 步 67/67:48 pass + 19 skip + 0 fail(37.09 s);ldd 确认 libc++

CPU-only 的 19 个 skip 均为 GPU/offload 依赖用例;MSVC 额外 2 个 skip 为已知的多配置
app 发现路径缺口。rapt_test_f16 在 Debug GPU 与 MSVC Debug 下均为实际执行并通过。

5.1 真实端到端训练

数据集 = datasets/tinystories_20k.nndataset(20,000 docs / 4,244,522 tokens /
66,321 个 seq64 窗口);GPT d_model=64 / heads=4 / layers=2 / d_ff=128 / seq_len=64,--batch-size 8 --accum-steps 2,20 update step,40HX:

配方 loss 轨迹(step 5/10/15/20) 结果
f32 8.7752 → 8.3832 → 8.0131 → 7.7011 1.8 s,无 NaN/冻结
--f16 8.7207 → 8.3779 → 7.9881 → 7.6188 1.5 s,无 NaN/冻结
--t1_58 8.8803 → 8.6901 → 8.4593 → 8.1366 4.5 s,无 NaN/冻结

f32 模型 warm start 1 step:loss 7.6060;保存文件 SHA-256 由
A060F06A…02D2 变为 0211B037…27D06,证明参数确实移动。

5.2 门禁与 AOT

  • bench/doc_inventory.ps1:52/52 engine virtual,L2-VIOLATIONS: 0,
    HANDWRITTEN-RESIDUE: 0,TERMINATING-CALLS: 0。
  • bench/gui_cli_audit.py:七节 PASS,可行动问题 0(使用最终 Release 二进制)。
  • bench/doc_align_audit.ps1 / bench/audit_dangling.ps1:可行动问题 0。
  • scan_exprs:库内 158 条融合表达式;RL PPO 梯度选择、value clip、GAE 与 reduction
    路径均进入 AOT 闭合世界。

6. 提交索引

主要能力提交从 fb21e21(架构冻结)到 2eb21a2(named PPO → TrainingSession);
独立发布审查修复提交为 1cb1c2b(基于 d822089)。正式发布另含一个
release: v1.12.0 提交,仅同步版本号、文档计数、发布说明和验收记录。审查期间远端
main 已合并许可证变更 PR #22(11987ef / merge 736c2a1),本版本通过合并保留
该 MIT → LGPL-3.0 变更;代码与构建测试结果不受影响。

7. 已知限制

  • OutputBundleLayer 当前是单输入 fan-out;任意多阶段 DAG 不在 v1.12 范围。
  • ModelSpec 保存 schema/packing 元数据,但不序列化任意自定义分支拓扑;具名模型仍由
    应用代码或领域工厂重建。
  • RLTrainingPipeline 自身 checkpoint 只固定 RNG、update/rollout 计数;experience
    buffer 与 replay policy 由 CheckpointProvider 的自定义 section 管理。
  • policy distribution 首版仅 categorical;连续动作与 multi-discrete 需实现
    PolicyDistribution。
  • 环境、MCTS、自对局、棋规与规则引擎不内置于库。