将 Vocos 声码器模型适配到华为昇腾 Ascend 910 NPU 上运行。
| 项目 | 说明 |
|---|---|
| 模型名称 | Vocos-mel-24kHz |
| 模型来源 | pengzhendong/vocos-mel-24khz (ModelScope) |
| 模型类型 | 声码器 (Vocoder):Mel 频谱图 → 音频波形 |
| 参数量 | 13.53M |
| 采样率 | 24000 Hz |
| 输入 | Mel 频谱图 (B, 100, T) |
| 输出 | 音频波形 (B, T×256) |
| 原始框架 | PyTorch |
| 依赖 | 版本 |
|---|---|
| OS | Ubuntu 22.04 LTS |
| Python | 3.11+ |
| PyTorch | 2.9.0 |
| torch_npu | 2.9.0.post1 |
| CANN | 8.5.1 |
| vocos | 0.1.0 |
| scipy | 1.17+ (音频保存 fallback) |
| NPU | Ascend 910 (9362) |
Vocos 模型在 NPU 上运行时,torch.istft 和 nn.functional.fold 算子不可用:
torch.istft 内部调用 nn.functional.fold → col2im → aclnnUnfoldGrad,NPU 不支持nn.functional.fold 直接调用 aclnnIm2colBackward,NPU 不支持用纯 PyTorch 手动实现 ISTFT 的 overlap-add 算法,替代 torch.istft:
torch.fft.irfft(NPU 原生支持)nn.functional.fold)n_fft//2 个样本vocos_npu.py:ISTFT 手动实现 + 模型 monkey-patch 加载_patch_istft_head():替换 ISTFT.forward 为 NPU 兼容版本istft_center():center padding 模式的手动 ISTFTistft_same():same padding 模式的手动 ISTFTVocos 的 ISTFTHead 调用 ISTFT 类的 forward,内部使用 torch.istft。通过 monkey-patch 替换 ISTFT.forward 为手动 overlap-add 实现,无需修改原始 vocos 库代码。
pip install vocos torch_npu torchaudio scipy modelscopepython3 -c "from modelscope import snapshot_download; snapshot_download('pengzhendong/vocos-mel-24khz')"import torch
import torch_npu
from vocos_npu import load_vocos_model, decode
# 加载模型到 NPU
model = load_vocos_model("npu:0")
# 准备 mel 频谱图 (B, 100, T)
mel = torch.randn(1, 100, 256, device="npu:0")
# 推理
with torch.no_grad():
audio = decode(model, mel)
print(f"输出音频: {audio.shape}, 设备: {audio.device}")# 生成 5 秒随机音频
python3 inference.py --generate --duration 5.0 --output output.wav
# 从 mel 频谱图文件生成
python3 inference.py --input mel.pt --output output.wav
# 指定设备
python3 inference.py --generate --duration 3.0 --device npu:0 --output output.wav以下为 NPU 上的实际推理输出(Ascend 910_9362,PyTorch 2.9.0 + torch_npu 2.9.0.post1):
============================================================
Vocos-mel-24kHz NPU 推理
============================================================
NPU 设备: Ascend910_9362
输入: Mel 频谱图 shape=torch.Size([1, 100, 937])
输出: 音频波形 shape=torch.Size([1, 239616])
时长: 9.98s
范围: [-0.106428, 0.094721]
✅ 推理成功
✅ 已保存到 output.wav
========================================================================================================================
Vocos-mel-24kHz NPU 适配验证报告
============================================================
【环境信息】
PyTorch: 2.9.0+cpu
torch_npu: 2.9.0.post1+gitee7ba04
NPU 可用: True
NPU 设备: Ascend910_9362
NPU 数量: 2
【1. CPU 参考推理 (torch.istft)】
输入 shape: torch.Size([1, 100, 256])
输出 shape: torch.Size([1, 65280])
输出范围: [-0.141037, 0.103343]
输出均值: -0.002615
输出标准差: 0.021002
【2. NPU 推理 (手动 overlap-add 替代 torch.istft)】
输入 shape: torch.Size([1, 100, 256])
输出 shape: torch.Size([1, 65280])
输出范围: [-0.141131, 0.103346]
输出均值: -0.002614
输出标准差: 0.021002
【6. 推理正常输出证据】
NPU 推理成功!
输入: Mel 频谱图 shape=torch.Size([1, 100, 937])
输出: 音频波形 shape=torch.Size([1, 239616])
时长: 9.98s
范围: [-0.106428, 0.094721]CPU 和 NPU 使用相同输入 Mel 频谱图,分别用 torch.istft 和手动 overlap-add 做 ISTFT 重建:
【3. CPU vs NPU 精度对比 (torch.istft vs 手动 overlap-add)】
最大绝对误差: 0.001573
平均绝对误差: 0.000144
MSE: 0.0000000381
PSNR: 74.19 dB
余弦相似度: 0.99995840
allclose(1e-2): ✅ 通过
allclose(1e-3): ❌ 未通过| T (帧数) | 音频时长 | 最大误差 | 平均误差 | PSNR (dB) | 余弦相似度 | allclose(1e-2) |
|---|---|---|---|---|---|---|
| 64 | 0.67s | 0.001003 | 0.000142 | 74.42 | 0.99996102 | ✅ 通过 |
| 128 | 1.35s | 0.001436 | 0.000142 | 74.34 | 0.99995863 | ✅ 通过 |
| 256 | 2.72s | 0.001499 | 0.000153 | 73.85 | 0.99995553 | ✅ 通过 |
| 512 | 5.45s | 0.001348 | 0.000155 | 73.75 | 0.99995470 | ✅ 通过 |
| 1024 | 10.91s | 0.002067 | 0.000157 | 73.60 | 0.99995363 | ✅ 通过 |
结论: 所有长度 allclose(atol=1e-2) 均通过,PSNR > 73 dB,余弦相似度 > 0.99995。误差来源于 Conv1d 等 FP32 算子在 CPU/NPU 上的浮点实现微小差异,不影响音频质量。
仅对比 ISTFT 算子本身(排除模型其他层的影响):
| 测试用例 | 最大误差 | PSNR (dB) | allclose |
|---|---|---|---|
| n_fft=1024 T=64 | 0.000000 | inf | ✅ |
| n_fft=1024 T=128 | 0.000000 | inf | ✅ |
| n_fft=1024 T=256 | 0.000000 | inf | ✅ |
| n_fft=1024 T=512 | 0.000000 | inf | ✅ |
ISTFT 算子级对比完美匹配(误差为零),说明手动 overlap-add 实现与
torch.istft完全等价。
python3 benchmark_accuracy.py【5. CPU vs NPU 性能对比 (T=468, 约5s音频)】
音频时长: 4.99s
CPU 推理均值: 246.4ms RTF=0.0494
NPU 推理均值: 53.5ms RTF=0.0107
加速比: 4.60x| 指标 | CPU (torch.istft) | NPU (手动 overlap-add) | 对比 |
|---|---|---|---|
| 推理延迟 | 246.4ms | 53.5ms | NPU 快 4.60x |
| RTF | 0.0494 | 0.0107 | NPU 快 4.60x |
| 实时倍率 | 20.2x | 93.5x | NPU 快 4.60x |
| T (帧数) | 音频时长 | 均值 (ms) | P50 (ms) | P95 (ms) | RTF | 实时倍率 |
|---|---|---|---|---|---|---|
| 64 | 0.67s | 7.85 | 7.77 | 8.05 | 0.0117 | 85.6x |
| 128 | 1.35s | 12.88 | 12.86 | 13.03 | 0.0095 | 105.2x |
| 256 | 2.72s | 23.53 | 23.58 | 23.81 | 0.0087 | 115.6x |
| 512 | 5.45s | 45.00 | 44.97 | 45.22 | 0.0083 | 121.1x |
| 1024 | 10.91s | 83.77 | 85.73 | 86.69 | 0.0077 | 130.3x |
python3 benchmark_performance.py# 完整验证 (环境检查 + 推理 + 精度对比 + 多长度测试)
python3 vocos_npu.py
# 快速 NPU 验证
python3 test_npu.pyvocos-mel-24khz-npu/
├── README.md # 部署文档
├── vocos_npu.py # 核心适配代码 (ISTFT 手动实现 + 模型加载)
├── inference.py # 命令行推理脚本
├── benchmark_accuracy.py # 精度评测脚本
├── benchmark_performance.py # 性能评测脚本
└── test_npu.py # NPU 验证测试torchaudio.save 在当前环境因 torchcodec 缺少 libnvrtc 而失败,推理脚本已添加 scipy fallbackVocos 原始项目: MIT License
本适配代码: MIT License