跳到正文
PyTorch Blog· Josiah Davis, Principal AI Engineer, Arm and Kshitij Sisodia, Principal Software Engineer, Arm·· 3 小时前AI 评分34

用 ExecuTorch 在 Arm 边缘设备上优化流式语音识别

Optimizing Streaming Speech Recognition on Arm® Edge Devices with ExecuTorch

AI 导读

PyTorch 团队将多语言流式 ASR 模型 Nemotron 3.5 经 ExecuTorch 部署到 Google Pixel 11,并分析精度与分块大小对流式质量的影响。

正文 · AI 翻译

当你对着设备说话时,你期望文字能随着你的讲话实时出现。这使得流式自动语音识别(ASR)与批处理转写成为不同的挑战——在批处理转写中,模型在开始前已拥有完整录音。强大的批处理准确率未必能延续到流式场景。一项跨模型 ASR 研究说明了这一差距。Qwen3-ASR-1.7B 在受测模型中取得了最佳的批处理准确率,但在使用 2.4 秒音频块进行评估时,其词错误率(WER)上升了77%。

在该研究的跨模型流式对比(表 5)中,NVIDIA® Nemotron™ Speech Streaming 0.6B 在 560 毫秒音频块上运行时具有最低的平均流式 WER。该对比指出了一个关键点:准确率必须在部署所用的分块节奏下进行测量。

本案例研究将较新的多语言模型Nemotron 3.5从PyTorch迁移到ExecuTorch,并在 Google Pixel 11 上分析其端侧执行情况。我们探讨精度和分块大小如何改变流式质量、在单推理线程下音频需要多少处理时间、工作负载的时间花在哪里,以及哪些原生内核会被运行。目标是找到一种同时评估准确率和延迟的实用方法。

在本篇博文中,你将了解到:

  1. ExecuTorch 如何将 PyTorch 模型连接到优化的 Arm CPU 内核。
  2. 为什么流式 ASR 需要自己的质量评估,以及更长的分块如何以更高延迟为代价提升最终转写准确率。
  3. Arm 可伸缩矩阵扩展 2(SME2)如何通过 FP16 和 INT8 量化(使用逐通道权重,QC8W)减少 ASR 总处理时间。
  4. 如何结合模型算子计时和原生内核采样来理解性能并识别剩余瓶颈。
  5. 如何同时选择分块大小和精度,以满足你的准确率和延迟目标。

从 PyTorch 模型到 CPU 指令

ExecuTorch 是 PyTorch 的边缘推理框架,包含导出工具和轻量级运行时。导出过程为推理准备模型,并生成一个.pte文件,设备运行时可以加载并执行该文件。

受支持的操作会被委托给XNNPACK,这是一个 CPU 推理库。在 Android™ 上,XNNPACK 可以从Arm® KleidiAI™软件中选择微内核:执行内部矩阵计算的小型优化例程。未委托给 XNNPACK 的算子使用 ExecuTorch 的可移植 CPU 内核运行。

图 1. 从模型导出到 CPU 指令。

SME2 扩展了 Arm 的指令集以加速矩阵计算,包括通用矩阵乘法(GEMM)。在采用 SME2 的Arm C1 CPU 集群实现中,矩阵单元由 CPU 集群中的核心共享,KleidiAI 提供微内核,用于受支持的操作。在构建中启用 SME2 会使这些路径可用。然而,需要原生性能分析才能显示实际运行了哪些内核。

一次流式调用包含什么

Nemotron 3.5 是一个多语言流式 ASR 模型,基于 RNN-T 架构构建,包含三个部分:

  1. 编码器 使用 FastConformer 注意力层和卷积层来表示音频。
  2. 预测器 使用 LSTM 来表示已输出 token 的历史。
  3. 联合器 使用一个小型前馈层,将编码器的音频表示与预测器的 token 历史表示相结合,并预测下一个 token。它还可以产生一个 空白,将解码推进到下一个音频位置。

前端将音频转换为对数梅尔特征向量,每 10 ms 产生一个向量。编码器将时间位置数量减少为原来的 8 分之一,因此其输出每 80 ms 音频对应一个位置。这创建了一个更紧凑的序列,表示相同的音频时长。

图 2. 从波形窗口到流式编码器位置。

前瞻 是一个块内可用的未来上下文;块节奏 是为一次调用收集新音频的频率。在前瞻为 13 时,一次调用收集 1,120 ms 的音频并产生 14 个编码器位置。预测器和联合器处理 全部 14 个有效位置,将其 token 累积到转录文本中。

前瞻 0、3 和 6 分别给出 80、320 和 560 ms 的块。更长的块会增加首次文本和后续更新的等待时间;预处理和推理在音频收集之后增加时间。

同时选择块大小和精度

我们在主机上使用 ExecuTorch 运行时及其 XNNPACK CPU 后端测量了转录准确率。我们创建了一个本地流式适配器,使用 Hugging Face Open ASR Leaderboard 评估框架 进行数据集准备、转录文本归一化和 WER 评分。

我们在四种块大小下评估了 FP32、FP16 和 INT8。INT8 规格为 QC8W,对符合条件的线性运算使用动态 INT8 激活和逐通道 INT8 权重,输出为 FP32。

图 3. 四个语料库上的流式 WER 与块大小关系。

上图中的每个点覆盖来自 LibriSpeech Other (LS Other)、AMI Cleaned、Earnings22 和 VoxPopuli Cleaned AA 数据集的 14,019 条话语。WER 将总词错误数除以所有四个语料库的总参考词数。

更长的块提高最终转录准确率。 从 80 到 1,120 ms,FP16 WER 从 15.2% 降至 11.5%,QC8W 从 15.5% 降至 11.7%。FP16 基本与 FP32 持平,在每个块大小下差异小于 0.03 个百分点,因此我们将 FP32 排除在进一步的性能分析之外。QC8W 保持了很强的准确率,相对于 FP32 增加了 0.21–0.31 个百分点 的 WER。

这些主机 WER 结果可为精度和前瞻选择提供依据。然而,它并未测量文本在设备上出现所需的时间。

在边缘设备上测试实时预算

我们在 Google Pixel 11 智能手机设备上处理了一段 24.9 秒的录音,使用 1,120 毫秒的分块,并将 一个推理线程绑定到中核 CPU。我们选择中核 CPU 作为该系统上持续流式工作负载的代表性目标。我们测试了 ExecuTorch 1.3.1 的两个构建版本,分别开启和关闭 SME2 支持。每个构建版本都保留了 XNNPACK 和 KleidiAI,并使用相同的模型产物。

每种配置都进行了两次预热和一次测量跟踪运行。总计时间涵盖从音频预处理到最终去标记化的整个已加载录音处理过程。

图 4. 禁用和启用 SME2 时的整段录音处理时间。

SME2 显著缩短了处理时间: FP16 从 9.79 秒降至 4.61 秒(快 2.12 倍),QC8W 从 5.20 秒降至 3.24 秒(快 1.61 倍)。

无论是否启用 SME2,两者处理录音的时间都远小于音频时长。用处理时间除以音频时长,我们计算出实时系数:在启用 SME2 时,FP16 为 0.19,QC8W 为 0.13。仅使用单个推理线程就提供了可观的处理余量。音频仍需先到达才能被解码,因此这一余量并不能消除分块收集延迟。但它为分块之间的其他 CPU 工作留出了容量,并有助于在持续转写期间管理热负载。

使用 ETDump 查找瓶颈

ETDump 记录 ExecuTorch 算子事件和计时。为了解 2.12 倍 FP16 和 1.61 倍 QC8W 的加速来自何处,我们将编码器、预测器和联合器中的机器学习(ML)算子分组为以下类别:

  • GEMM(蓝色): 矩阵乘法,主要是编码器的全连接层。
  • 数据移动(橙色): 复制、拼接、重复和嵌入查找。
  • 逐元素(红色): 激活、比较和其他逐值运算。
  • 卷积与归一化(绿色和紫色): 卷积滤波器和归一化算子;两者在此处占比相对较小。
  • 其他(紫罗兰色): 其余计时的少量操作,例如张量创建。
  • 开销(灰色): 分组算子事件之外的完整运行时间;这可能包括运行器和框架开销。

图 5. 整次运行加速背后的算子成本和开销。

ETDump 计时是编码器、预测器和联合器网络的总和。加上剩余开销即得到图 4 所示的完整处理时间。

GEMM 贡献了大部分加速。

启用 SME2 后,GEMM 时间从 FP16 的 8.2 秒降至 3.1 秒,QC8W 从 4.1 秒降至 2.0 秒。GEMM 仍是运行中占比最大的部分,但其在总处理时间中的份额下降:FP16 从 84% 降至 67%,QC8W 从 78% 降至 62%。两个构建版本的数据移动耗时大致相同,因此随着 GEMM 加速,其相对份额上升:FP16 从 8% 升至 17%,QC8W 从 9% 升至 17%。这部分剩余工作限制了整体加速幅度,也为进一步优化提供了目标。

运行了哪些内核?

ETDump 能定位开销大的算子族,但不会指出执行这些算子的原生微内核。

Arm Streamline 让我们能够采样原生调用路径并测量硬件计数器。在 Pixel 11 上,我们测得 FP16 的 SME 利用率为 38.4%,QC8W 为 53.7%。这表明每次采集期间矩阵硬件被分配的比例,而非峰值算术吞吐量的百分比。我们还采样了 GEMM 函数,以识别各构建版本所选择的微内核。

函数名揭示了所采样的路径。_sme2_mopa 后缀表示矩阵外积累加例程。NEON 和 I8MM 是控制路径所使用的向量指令族。

精度 SME2 采样的 GEMM 路径与函数
FP16 True KleidiAI FP16 SME2
kai_kernel_matmul_clamp_f16_f16p2vlx2_f16p2vlx2_2vlx2vl_sme2_mopa

XNNPACK FP16 NEON
xnn_f16_gemm_minmax_ukernel_6x16__asm_aarch64_neonfp16arith_cortex_a75
FP16 False XNNPACK FP16 NEON
xnn_f16_gemm_minmax_ukernel_6x16__asm_aarch64_neonfp16arith_cortex_a75
QC8W True KleidiAI INT8 SME2,FP32 输出
kai_kernel_matmul_clamp_f32_qai8dxp1vlx4_qsi8cxp4vlx4_1vlx4vl_sme2_mopa

KleidiAI FP32 SME2
kai_kernel_matmul_clamp_f32_f32p2vlx1_f32p2vlx1biasf32_sme2_mopa
QC8W False KleidiAI INT8 NEON I8MM,FP32 输出
kai_run_matmul_clamp_f32_qai8dxp4x8_qsi8cxp4x8_16x4_neon_i8mm

这些采集结果证实,面向 SME2 的 KleidiAI GEMM 内核在 Pixel 11 上针对 FP16 和 QC8W 均运行了,同时还运行了其他内核路径。在 FP16 构建版本中,部分 GEMM 操作仍使用 NEON。在 QC8W 构建版本中,部分 GEMM 操作仍以 FP32 运行。

这凸显了生态系统中的工具链缺口。ETDump 暴露模型算子耗时,而 Streamline 采样原生函数,但两者都无法直接关联这些视图。将单个模型层映射到所观察到的内核函数仍属未来工作。

选择工作点

部署需要在精度和分块大小之间权衡响应延迟与准确率。应用可能从准确率目标或延迟预算出发;以下示例说明了这两种方法。

下面的图 6 将主机 WER 结果与 Pixel 11 上启用 SME2 的 FP16 和 QC8W 组件基准测试配对展示。灰色刻度标记音频采集结束的时间;虚线部分加上实测的计算延迟。

x 轴是条件性首 token 时间估计:音频采集时间加上编码器–预测器–联合器序列时间的中位数。组件基准测试使用合成输入、全新流状态,并在三轮中对每种配置测量了 75 个样本。它假设首个输出为文本。

图 6. 启用 SME2 时的 WER 与估计首 token 延迟对比。

以示例性的13% WER 上限为参照,FP16 和 QC8W 在320、560 和 1,120 ms分块大小下均符合要求。320 ms 分块更有利于更早响应,FP16 的 WER 为12.67%,QC8W 为12.97%。更长的分块可提升准确率,在 1,120 ms 时分别达到11.50%和11.72%,但需要更多音频到达后才开始出现转写文本。

对于800 ms 延迟预算,两种精度在320 ms和560 ms下均处于预算之内,同时也低于示例性的13% WER 上限。320 ms 配置更有利于更早响应,而 560 ms 则提供更好的准确率。在 560 ms 下,FP16 结合了12.01% WER与估计的691 ms延迟,而 QC8W 结合了12.26%与660 ms。此处,两种 80 ms 配置均未达到 WER 目标。相反,两种 1,120 ms 配置均未达到延迟预算。

结论:这对开发者意味着什么

  • 在预期的分块大小下评估流式 ASR。整段录音的准确率并不能预测流式质量。此处更长的分块提升了最终转写准确率,同时增加了响应延迟。
  • ExecuTorch 将 PyTorch 模型连接到优化的 Arm CPU 内核。其导出和运行时路径让 XNNPACK 为符合条件的操作选择 KleidiAI 微内核。
  • SME2 创造了更多处理余量。加速矩阵运算减少了 ASR 所花费的时间,为设备上的其他应用任务或并发工作负载留出更多空间。
  • ETDump 揭示了算子加速和剩余瓶颈。对算子计时进行分组可显示收益来源,以及数据移动如何成为处理时间中更大的占比。
  • Streamline 识别出实际运行的原生微内核。原生采样确认了 SME2 内核的选择,而硬件计数器则显示矩阵硬件的分配情况。
  • 同时选择分块大小和精度。比较精度与分块大小的组合有助于开发者为其应用在响应延迟与转写准确率之间取得平衡。

文章 Optimizing Streaming Speech Recognition on Arm® Edge Devices with ExecuTorch 首次发表于 PyTorch。

来源:PyTorch Blog · pytorch.org