Qwen3-TTS 0.6B CustomVoice 的 pnnx/ncnn 移植与 macOS/Linux 严格一致性验证 #6832
SuLea-IT
started this conversation in
Show and tell
Replies: 1 comment
最终发布补充(2026-07-17)
该运行的 Ubuntu、macOS、Windows 三个 CMake job 均为 本修复不改变 Qwen3-TTS 图、权重、C++ 推理路径或已报告的 parity 结果。最终机器门禁为 |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Qwen3-TTS 0.6B CustomVoice 的 pnnx/ncnn 移植与 macOS/Linux 严格一致性验证
对应任务:Tencent/ncnn#6791
公开仓库:https://github.com/SuLea-IT/Qwen3-TTS-ncnn
验证实现提交:
a323153c991d517fbd919640d700eef453b1066b1. 完成范围
本项目将官方
Qwen/Qwen3-TTS-12Hz-0.6B-CustomVoice转换为 ncnn模型,并在 C++ 中完成以下离线路径:
最终运行程序不依赖 Python、PyTorch、Transformers、pnnx、ONNX Runtime
或 libtorch。验收范围固定为 0.6B CustomVoice、batch 1、offline、greedy、
CPU FP32;采样、流式、1.7B、Base/VoiceDesign、量化与 Vulkan 属于后续矩阵。
2. 固定版本
022e286b98fbec7e1e916cb940cdf532cd9f488e85e237c12c027371202489a0ec509ded67b5e4b513b6d5318c73be53bb386fa51e8067615d0eb7c120260526,实际 executable SHA-25640eba51b11f29a12b847d1cfa6abceb0fec60f1b7afeef37d8481a0ace865030官方 checkpoint 的 9 个文件由
checkpoint.json逐项验证;最终 CPU转换包由
conversion-assets-cpu.json锁定 80 个文件,manifest SHA-256 为cbbb3959a7bb79735ea7f546d03e502ae8bd1e16824d020ace0bdbf3b58eedfd。3. 关键问题与修复
3.1 不能用 full recompute 代替官方 KV 路径
早期 25 帧参考每帧重算完整 prefix,并在第 6 帧出现 greedy 分支变化。
这不能证明增量 KV cache 的正确性。本项目直接调用固定官方 wrapper 的
DynamicCache生成路径,并 hook Talker 与 Code Predictor 的 logits、K/V、RoPE、mask、hidden 和 codes。
官方生成
N个完整 codec frame 实际需要N+1次 Talker token 选择:k>0消费上一主码并完成一行 16-code frame;N完成最后一帧,同时从 logits 选择 lookahead/EOS。因此自然 EOS 运行的 54 帧对应 Talker step
0..54,而不是 54 次 forward。本项目把这个映射写成机器断言,避免 off-by-one 或把 EOS 错当成一行 codes。
3.2 C++ 对齐官方 logits processor
主码本不再直接裸
argmax,而是依次实现并测试:1.05,正/负 logits 与 Transformers 算法一致;2048..3071,但恢复 EOS2150;min_new_tokens=2前禁止 EOS;torch.argmax的最低 index tie 行为;3.3 干净 pnnx 转换必须形成闭包
转换器从空 output/work 目录开始,验证 checkpoint,记录 pnnx wrapper 与
实际 executable hash、完整 argv、Python/平台和所有转换脚本 hash;每次图
重写要求精确命中计数,零命中、少命中、重复 patch 都失败;输出不得含
残余
pnnx.*/Tensor.*层或 symlink。两个独立空目录的 CPU 转换 A/B 最终 80/80 文件逐字节一致。随后使用 clean-B
而不是继承下载包重新跑 25 帧与自然 EOS 54 帧 parity,关闭了“manifest 与
运行模型不是同一产物”的证据断点。
3.4 float 到 PCM16 的最后一 LSB
官方
soundfile/libsndfile的 float→PCM16 行为不是简单四舍五入。本项目改为clip 到
[-1,1]、乘32768、向负无穷取整,NaN 输出静音,并增加边界单测。在修正且使用官方 soundfile fixture 后,两帧 3,840 个 PCM 样本可逐字节一致。
3.5 低内存 Linux 的模型生命周期
FP32 模型很大。运行时采用固定 ncnn revision 已有的
Option::use_mapped_model_loading,prompt 构建后释放 frontend,生成完整整数 codes 后释放 Talker/Code Predictor 和 cache,再进入固定 325 帧 speech
decoder,避免所有大网络同时常驻。
在只有约 3.6 GiB RAM、原 1.9 GiB swap 已满的 Ubuntu 主机上,最终验证使用:
nohup + setsid,不依赖 SSH 会话;-j1、模型与 BLAS 单线程;swapoff与删除;time -v记录资源。最终 12 项 CTest 用时 641.83 秒,真实模型项 618.04 秒,最大 RSS 记录
7,433,148 KiB;结束状态为
exit_code=0、swap_cleanup_ok=true,未修改fstab,也未停止服务器其他服务。3.6 fail-closed 稳健性
新增门禁包括:
1x、0、负数和溢出;memcpy前验证;4. 严格一致性结果
固定输入:
1.73e-6;SNR114.9 dB;PCM max1LSBmax_frames=1001.71e-6;SNR114.75 dB;PCM max1LSB自然终止证据还验证:Code Predictor 恰好
54*15次;最后 processedlookahead 为 EOS
2150;内部最大 token 数 101 尚未达到,因此不是长度截断。5. 双平台 CMake 结果
d633b2c55ae7493521e9748a20b20748cb4d1680d654aec63d4c555ee73b4397libc++/libSystem,无 RPATHc848cec24fc544c62476b9221c0822e9801b7d354bc793e0ee3dcc5567bce2b5libstdc++/libm/libgcc_s/libc与系统 loader,无 RPATH/RUNPATH两边的安装程序与各自实际通过 CTest 的 build-tree 程序逐字节相同。Linux
安装程序还独立跑了一次真实两帧模型:10:20.98 退出 0,32/32 codes
和 3,840 个 PCM 样本全部与官方 fixture 逐字节一致;并在
/tmp下运行--help,排除了工作目录依赖。发布前又从完整 Git bundle 克隆到全新目录,在无网络、固定 ncnn/json
源码下完成 296/296 编译步骤和 8/8 host CTest。该审计先暴露出
编译参数检查器将 ncnn 按单个源文件设置的 ARM dispatch ISA 参数误报为
全局污染;修复后豁免必须同时匹配规范化 ncnn 根目录、架构目录与专用文件名,
项目源、普通 ncnn 源、架构不匹配和伪造相似路径仍会失败。修复后 macOS
12/12、Ubuntu 相关 9/9 复跑全过。全新安装程序与 build-tree 程序字节相同,
SHA-256 为
cacc9e50d2e741da43bf8d7b4498ab481590035e4937c67a832c04c518e1ca94,仅依赖系统
libc++/libSystem,无LC_RPATH。6. 复现入口
转换与完整命令见
models/qwen3-tts/README.md。最小构建形式:Linux host-only ASan/UBSan 使用
linux-x86_64-sanitizerspreset:Debug sanitizer构建完成 222 步,8/8 host/negative CTest 全过,无 sanitizer 报告。低内存模型
测试使用
tools/run_linux_low_memory_ctest.sh。7. 开源复用与边界
工程基线来自
March-77/ncnn_llm@f46ec001...,并保留 nihui、LudovicoYIN 与 mingshi2333 相关实现的 Apache-2.0 署名。本轮直接使用的
上游运行时 API 是固定 ncnn 的 mapped model loading;相关 PR/Discussion 只
作为调研线索,不能替代本地可复查证据。完整来源和许可证见
THIRD_PARTY.md与OPEN_SOURCE_RESEARCH.md。8. 已知边界
本次没有声称 sampling RNG、真正流式输出、1.7B、Base voice clone、
VoiceDesign、INT8/FP16/Vulkan parity。299/300/301 当前是调度与缓冲边界门禁;
固定 325 帧 decoder 已被真实两帧 smoke 运行,但尚未发布官方 300 帧 waveform
fixture。这些属于后续扩展,不影响 #6791 核心离线 CustomVoice 路径的验收。
All reactions