NPU硬件:A2/910B
操作系统:ARM
部署方式:单卡
推理框架:Triton Inference Server
WeNet 是一个开源的端到端语音识别框架,旨在通过简化传统语音识别系统的复杂性,提供高效、灵活且准确的语音识别解决方案。它结合了最新的深度学习技术,广泛应用于学术研究和工业场景。
apt update;
apt install zlib1g-dev;
apt install openssl;
apt install libssl-dev;
apt install libxml2-dev;
apt install libcurl4-openssl-dev;
apt install libarchive-dev;
pip install distro --trusted-host pypi.org --trusted-host files.pythonhosted.orggit clone https://github.com/triton-inference-server/server.git
cd server
git checkout r24.12if target_platform() != "windows":
all_backends = [
"ensemble",
#"identity",
#"square",
#"repeat",
#"tensorflow",
#"onnxruntime",
"python",
#"dali",
#"pytorch",
#"openvino",
#"fil",
#"tensorrt",
]./build.py -v --enable-all --no-container-build --build-dir='pwd'/build
cp -r build/opt/tritonserver /opt/opt/tritonserver/bin/tritonserver --model-repository=${MODEL_DIR}获取wenet预训练权重wenet-e2e/wenet-github
获取WeNet om转换脚本和离线推理脚本 wenet-modelzoo
export PYTHONPATH=./wenet #wenet源码路径
python3 export_onnx_npu.py --config ./train.yaml --checkpoint ./final.pt --output_onnx_dir ./onnx/ --num_decoding_left_chunks 4 --reverse_weight 0.3 --cmvn_file ./train/global_cmvn转换成功后得到offline_encoder.onnx 和 decoder.onnx 2. encoder转非流式动态分档om
export batch_size=1
atc --input_format=ND --framework=5 --model=/disk1/liangliang/wenet/onnx_model/onnx/offline_encoder.onnx --input_shape="speech:${batch_size},-1,80;speech_lengths:${batch_size}" --dynamic_dims="262;326;390;454;518;582;646;710;774;838;902;966;1028;1284;1478" --output=/disk1/liangliang/om-wenet/offline_encoder_static_bs${batch_size} --log=error --soc_version=Ascend910B3### static_decoder.sh
batch_size=1
SOC_VERSION=Ascend910B3
atc --model=./onnx/decoder.onnx --framework=5 --output=./om-wenet/offline_decoder_static_${batch_size} --input_format=ND \
--input_shape="encoder_out:${batch_size},-1,256;encoder_out_lens:${batch_size};hyps_pad_sos_eos:${batch_size},10,-1;hyps_lens_sos:${batch_size},10;ctc_score:${batch_size},10" --log=error \
--dynamic_dims="96,5;96,6;96,7;96,8;96,9;96,10;96,11;96,12;96,13;96,14;96,15;96,16;96,17;96,18;96,19;96,20;144,5;\
144,6;144,7;144,8;144,9;144,10;144,11;144,12;144,13;144,14;144,15;144,16;144,17;144,18;144,19;144,20;\
144,21;144,22;144,23;144,24;144,25;144,26;144,27;144,28;144,29;384,5;384,6;384,7;384,8;384,9;384,10;384,11;\
384,12;384,13;384,14;384,15;384,16;384,17;384,18;384,19;384,20;384,21;384,22;384,23;384,24;384,25;384,26;\
384,27;384,28;384,29;384,30;384,31;384,32;384,33;384,34;384,35;384,36;384,37;384,38;384,39;384,40;384,41;\
384,42;384,43;384,44;" \
--soc_version=${SOC_VERSION}通过以上链接下载whl包,用于离线安装,aclruntime根据python版本选择对应whl包;
#安装aclruntime
pip3 install ./aclruntime-0.0.2-cp311-cp311-linux_aarch64.whl
#安装ais_bench推理程序
pip3 install ./ais_bench-0.0.2-py3-none-any.whlgit clone https://github.com/Slyne/ctc_decoder.git
apt-get update
apt-get install swig
apt-get install python3-dev
cd ctc_decoder/swig && bash setup.shexport batch_size=1
export ASCEND_RT_VISIBLE_DEVICES=0
export PYTHONPATH=./wenet
python3 recognize_om.py --config=./train.yaml --test_data=./aishell/s0/data/test/data.list --dict=onnx_model/lang_char.txt --mode=attention_rescoring --result_file=static_result.log --encoder_om=./offline_encoder_static_bs1.om --decoder_om=./offline_decoder_static_1.om --batch_size=1 --device_id=0 --static --test_file=static_test_result.txt --num_process=8 --encoder_gears="262, 326, 390, 454, 518, 582, 646, 710, 774, 838, 902, 966, 1028, 1284, 1478" --decoder_gears="96, 144, 384"使用aishell数据集测试离线性能:
| 进程数 | decode类型 | 耗时 | 推理效率(s/s) | npu利用率 |
|---|---|---|---|---|
| 16 | ctc_greedy | 19 | 1897 | 88% |
| 16 | attention_rescoring | 29 | 1243 | 70% |
model_repository/
└── model/
├── 1/
│ └── model.py
└── config.pbtxtname: "asr_om_model"
backend: "python"
# 输入配置(WAV文件路径列表)
input [
{
name: "wav_paths"
data_type: TYPE_STRING
dims: [-1] # 动态维度,支持批量输入多个WAV路径
}
]
# 输出配置(ASR识别结果列表)
output [
{
name: "asr_results"
data_type: TYPE_STRING
dims: [-1]
}
]
# 模型参数配置(需与model.py中的参数解析对应)
parameters [
# 必选参数:OM模型路径
{
key: "encoder_om_path"
value: { string_value: "./om-wenet/offline_encoder_static_bs1.om" } # 替换为实际encoder OM路径
},
......
]
# 资源限制(根据实际硬件调整)
instance_group [
{
count: 8 # server实例数量
kind: KIND_CPU # Python后端选择CPU,实际特征提取和推理调用NPU
}
]import triton_python_backend_utils as pb_utils
# 导入特征提取依赖
import torch
import torchaudio
import torchaudio.compliance.kaldi as kaldi
import torch_npu
from ais_bench.infer.interface import InferSession
import ...
def get_dict(dict_path: str) -> tuple[List[str], Dict[int, str]]:
"""加载字符字典"""
def preprocess_audio(audio_path: str, device_id: int = 0) -> tuple[np.ndarray, np.ndarray, float]:
# 音频文件特征提取
def _extract_feats_multi_thread(wav_paths: List[str], device_id: int, feature_workers: int) -> List[tuple]:
# 音频文件多线程特征提取(选用)
class TritonPythonModel:
def initialize(self, args: Dict):
"""初始化1个OM实例"""
def _parse_parameters(self) -> Dict:
"""参数解析(必选/可选参数校验)"""
def _static_shape_pad(self, feats: np.ndarray, feats_lengths: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
"""静态形状填充:适配OM输入要求,动态dims"""
def _decode_ctc_greedy(self, beam_log_probs_idx: np.ndarray, encoder_out_lens: np.ndarray) -> str:
"""CTC贪心解码:基于char_dict映射"""
def execute(self, requests):
"""推理核心:1. 解析输入:wav_paths 2.调用_preprocess_audio 3. 单OM实例推理 4. 构造Triton响应"""
def finalize(self):
"""模型销毁:仅输出日志(OM实例由InferSession自动释放)"""# 修改核心点:
# spectrum = torch.fft.rfft(strided_input).abs() #原先的abs算子不适配,有输入类型报错
real_view = torch.view_as_real(torch.fft.rfft(strided_input)) #替换
spectrum = torch.sqrt(real_view[..., 0].pow(2) + real_view[..., 1].pow(2))1、将patch放到torchaudio的路径下,如果路径不一致请自行修改
pip show torchaudio
cp fbank_npu.patch /usr/local/lib/python3.11/site-packages/torchaudio/
2、在torchaudio路径下执行补丁
patch -p1 < fbank_npu.patch使用方法修改:在kaldi.fbank方法前,将waveform转到npu上,生成得到speech后再转到cpu上;
waveform = waveform.to(torch.device("npu:0"))
······
speech = features.unsqueeze(0).cpu().numpy()export PYTHONPATH=/xxx/wenet #需要声明wenet源码的路径
/opt/tritonserver/bin/tritonserver --model-repository=/xxxxx/asr_repo --http-port=8083 --grpc-port=8084 --metrics-port=8085 #model-repository要设为wenet_om_model的上层文件夹
用aishell 7176条测试集进行测试,decoder选择ctc_greedy:
| 场景 | 并发 | 耗时(s) | 推理效率(s/s) |
|---|---|---|---|
| 1实例 | 200 | 93 | 388 |
| 8实例 | 200 | 15.4 | 2341 |
| 12实例 | 200 | 11.5 | 3135 |
测试对比发现,在单卡12实例时推理吞吐最大、效率最高,相比优化前性能明显。
(1)Q:报错 NPU function error: at_npu::native::AclSetCompileopt(aclCompileOpt::ACL_PRECISION_MODE, precision_mode), error code is 500001
A:triton启动时如果遇到以上报错,通过source /usr/local/Ascend/ascend-toolkit/set_env.sh解决;
(2)Q:多实例启动时,推理节点显示:unhealth;stub process is unhealthy and it will be restarted
A:观察运行内存是否打满,如果是内存不足导致的则增加内存。