本文档记录 Irodori-TTS-500M-v2 在华为昇腾 NPU 环境的部署与验证结果。
Irodori-TTS-500M-v2 是一个基于 Rectified Flow Diffusion Transformer (RF-DiT) 架构的日语文本转语音(TTS)模型,支持零样本语音克隆和基于 emoji 的风格控制。原始仓库为 Aratako/Irodori-TTS。
本次昇腾适配主要完成以下工作:
irodori_tts/inference_runtime.py 中增加 npu 设备识别、同步与缓存清理支持irodori_tts/codec.py 中将默认设备从 cuda 改为 npuirodori_tts/model.py 中修复 scaled_dot_product_attention 的 attn_mask shape,以兼容 Ascend NPU aclnnFlashAttentionScore 算子要求inference.py 一键推理脚本,支持本地权重加载与 tokenizer 路径覆盖相关获取地址:
| 组件 | 版本 |
|---|---|
torch | 2.9.0+cpu |
torch-npu | 2.9.0.post1+gitee7ba04 |
transformers | 4.57.6 |
dacvae | 1.0.0 |
CANN | 8.5.1 |
910B4 x 1./weights/model.safetensorsinference.py使用华为 PyPI 镜像加速安装:
pip install -i https://repo.huaweicloud.com/repository/pypi/simple \
transformers sentencepiece safetensors torchaudio soundfile \
huggingface-hub torchcodec
# dacvae 需要从 GitHub 安装
pip install "dacvae @ git+https://github.com/facebookresearch/dacvae.git"
# audiotools 用于参考音频响度归一化(可选)
pip install git+https://github.com/descriptinc/audiotools.gitexport HF_ENDPOINT=https://hf-mirror.com
huggingface-cli download Aratako/Irodori-TTS-500M-v2 model.safetensors --local-dir ./weights或从 ModelScope 下载:
modelscope download --model Aratako/Irodori-TTS-500M-v2 --local_dir ./weightsexport HF_ENDPOINT=https://hf-mirror.com
huggingface-cli download Aratako/Semantic-DACVAE-Japanese-32dim weights.pth --local-dir ./weights/codecexport HF_ENDPOINT=https://hf-mirror.com
huggingface-cli download llm-jp/llm-jp-3-150m tokenizer.json tokenizer_config.json --local-dir ./weights/tokenizer下载完成后目录结构:
./weights/
├── model.safetensors
├── codec/
│ └── weights.pth
└── tokenizer/
├── tokenizer.json
└── tokenizer_config.jsonpython inference.py \
--text "お電話ありがとうございます。ただいま電話が大変混み合っております。" \
--output-wav output_standard.wav \
--model-device npu \
--codec-device npu \
--num-steps 20 \
--seed 42 \
--no-refpython inference.py \
--text "お電話ありがとうございます。ただいま電話が大変混み合っております。" \
--output-wav output_clone.wav \
--model-device npu \
--codec-device npu \
--num-steps 20 \
--seed 42 \
--ref-wav /path/to/reference.wav| 参数 | 说明 |
|---|---|
--model-device | 模型推理设备,npu / cuda / cpu |
--codec-device | Codec 编解码设备,npu / cuda / cpu |
--model-precision | 模型精度,fp32 / bf16(NPU 支持 bf16) |
--codec-precision | Codec 精度,fp32 / bf16 |
--num-steps | 扩散步数,默认 40,可减少以加速推理 |
--no-ref | 不使用参考音频,用于标准 TTS |
--ref-wav | 参考音频路径,用于语音克隆 |
提供一键评测脚本 eval_ascend.py,自动执行精度对比(NPU vs CPU)与性能基准测试:
# 完整评测(精度 + 性能)
python eval_ascend.py \
--text "お電話ありがとうございます。" \
--num-steps 20 \
--seed 42 \
--num-runs 3
# 仅性能测试
python eval_ascend.py --skip-accuracy
# 仅精度测试
python eval_ascend.py --skip-performance评测脚本功能:
./weights/ 目录不存在权重文件,自动从 ModelScope 下载精度对比条件:num_steps=3, seed=42, text="お電話ありがとうございます",NPU(fp32) vs CPU(fp32) 相同 seed 确定性推理。
使用 3 步推理(CPU 1步 ~84s,3步 ~70s 可接受),固定初始噪声生成器为 CPU Generator 以消除 PRNG 差异。
| 指标 | 数值 |
|---|---|
| 相对误差 (L2) | 0.0405% |
| SNR | 67.85 dB |
| MSE | 6.76e-09 |
| 最大逐点差异 | 0.0003 |
| 判断结果 | ✅ 通过(相对误差 < 1.0%) |
结论:NPU 与 CPU 的输出音频在相同 seed 下几乎完全一致,相对误差仅 0.04%,远低于 1% 阈值,说明昇腾 NPU 的算子计算精度满足 TTS 推理要求。
关键修复:初始噪声必须使用 CPU 生成器(
torch.Generator(device="cpu")),因为 NPU 生成器的 PRNG 序列与 CPU 不同,会导致 ~132% 的假误差。
性能测试条件:num_steps=20, seconds=5.0, device=npu, precision=fp32。
| 指标 | 数值 |
|---|---|
| 总耗时 | 16.05 s |
| 扩散模型推理 | 840.6 ms (42ms/step) |
| Codec 解码 | 544.6 ms |
| 生成音频长度 | 3.80 s |
| 实时率 | 4.22 x |
各阶段耗时分解:
| 阶段 | 耗时 |
|---|---|
tokenize_text | 0.8 ms |
prepare_reference | 0.2 ms |
sample_rf | 840.6 ms |
unpatchify_latent | 0.1 ms |
decode_latent | 544.6 ms |
分析:扩散模型推理(
sample_rf)在 20 步下仅 840ms,平均每步约 42ms;Codec 解码(decode_latent)约 545ms。总耗时 16s 包含模型加载 / JIT 编译。
已验证通过的推理命令见 5.1 节。标准 TTS 在 NPU 上推理成功,输出音频文件 output_standard.wav。
本次适配涉及以下源码修改:
irodori_tts/inference_runtime.py_is_npu_available() 检测resolve_runtime_device():增加 npu 分支校验list_available_runtime_devices():NPU 可用时优先返回 npulist_available_runtime_precisions():NPU 支持 bf16_sync_device():增加 torch.npu.synchronize()resolve_runtime_dtype():放宽 bf16 限制到 cuda 或 npuunload():增加 torch.npu.empty_cache()irodori_tts/codec.pyDACVAECodec.load() 默认设备从 cuda 改为 npuirodori_tts/model.pySelfAttention.forward():将 attn_mask 从 [B, 1, 1, S] 显式扩展为 [B, 1, S, S]JointAttention.forward():将 attn_mask 从 [B, 1, 1, total_kv] 显式扩展为 [B, 1, S, total_kv]修改原因:Ascend NPU 的 aclnnFlashAttentionScore 算子要求 attn_mask shape 必须为 [B, N, Sq, Skv]、[B, 1, Sq, Skv]、[1, 1, Sq, Skv] 或 [Sq, Skv]。原始代码中的 [B, 1, 1, S] 虽可在 CUDA 上通过广播生效,但在 NPU 上会直接触发 EZ9999 Tiling 失败。
irodori_tts/rf.py_make_rng():将 torch.Generator(device=device) 改为始终使用 torch.Generator(device="cpu")修改原因:NPU 的随机数生成器(PRNG)序列与 CPU 不同,即使使用相同 seed 也会产生不同的初始噪声。扩散模型的初始噪声由 torch.Generator 生成,NPU vs CPU 噪声不同会导致输出音频完全不一致(实测相对误差 ~132%)。将生成器固定为 CPU 可确保跨设备相同 seed 产生相同噪声。
eval_ascend.py(新增)run_single_inference():封装模型加载、推理、计时等逻辑,支持 NPU/CPU 设备选择。run_accuracy_test():NPU 确定性检验 + NPU vs CPU 精度对比(3-step),自动判定是否 < 1%。run_performance_benchmark():多轮性能测试,输出各阶段耗时与 RTF。EMOJI_ANNOTATIONS.md。bf16,可在 --model-precision bf16 下尝试,但需验证音质是否满足要求。torchcodec,请执行 pip install torchcodec。