NVIDIA NeMo 持续开发了设定行业基准的 自动语音识别(ASR) 模型,尤其是在 Hugging Face Open ASR 排行榜 上拔得头筹的模型。
这些可将语音转录为文本的 NVIDIA NeMo ASR 模型提供了一系列旨在优化速度和准确性的架构:
- CTC 模型 ( NVIDIA/parakeet-ctc-1.1b ):此模型具有 FastConformer 编码器和 softmax 预测头。它是非自回归的,这意味着未来的预测不依赖于之前的预测,从而实现快速高效的推理。
- RNN-T 模型 ( NVIDIA/parakeet-rnnt-1.1b ):此传感器模型向 FastConformer 编码器添加了预测和联合网络,使其成为自回归模型 – 每个预测都取决于先前的预测历史。由于此属性,人们普遍认为 RNN-T 模型的 GPU 推理速度较慢,更适合 CPU。
- TDT 模型 ( NVIDIA/parakeet-tdt-1.1b ):另一个传感器模型,但使用名为 token-and-duration 传感器 (TDT) 的改进传感器目标进行训练。虽然仍然是自回归模型,但它可以在每个步骤中执行多个预测,从而加快推理速度。
- TDT-CTC 模型 ( parakeet-tdt_ctc-110m ):这是传感器和 CTC 解码器的混合变体,可同时引入两个解码器,从而在训练期间加快收敛速度。它只需训练一个模型即可训练两个解码器。
- AED 模型 ( NVIDIA/canary-1b ):Attention-encoder-decoder (AED) 模型也基于 FastConformer,具有自回归性,能够以额外计算为代价提供更高的准确性(更低的 词错误率或 WER )。
以前,这些模型面临速度性能瓶颈,例如投射开销、低计算强度和发散性能问题。
在本文中,您将了解 NVIDIA 如何通过将张量自动投射到 bfloat16
、创新的标签循环算法以及引入 NeMo 2.0.0 中可用的 CUDA Graphs 等关键增强功能,将 NeMo ASR 模型的推理速度提升高达 10 倍(图 1)。
克服速度性能瓶颈
本节将深入探讨 NVIDIA 自动语音识别(ASR)模型如何克服各种速度性能瓶颈,包括投射开销、批量处理优化、低计算强度和发散性能问题。
自动混合精度会产生额外开销
从 NeMo 的早期开始,便一直在 torch.amp.autocast 上下文管理器中 执行推理。这将在矩阵乘法之前自动将 float32
权重投射到 float16
或 bfloat16
,从而实现半精度张量核心运算的使用。在幕后,自动混合精度(AMP)维护一个“投射缓存”,用于存储这些转换,通常会加快训练速度。然而,会出现以下问题:
- 过时的自动投射行为 :自动投射是在
softmax
和layer norm
等运算较为罕见时开发的。在像 Conformers 和 Transformers 这样的现代模型中,这些运算很常见,会 将float16
或bfloat16
输入投射回 float32 ,从而在每次矩阵乘法之前导致额外的投射。 - 参数处理: 要使 AMP Cast 缓存有效,参数需要
requires_grad=True
。遗憾的是,在 NeMo 转录 API 中,此标志设置为 False(requires_grad=False
),从而阻止缓存工作,并导致不必要的 Cast 开销。 - 频繁的缓存清除 :每次退出
torch.amp.autocast
上下文管理器时,都会清除转换缓存。用户通常会在上下文管理器中包装单个推理调用,从而无法有效利用缓存。
这些额外投射的开销非常高。图 2 显示了 Parakeet CTC 1.1B 模型中矩阵乘法之前的投射如何增加 200 微秒的开销,而矩阵乘法本身仅需 200 微秒,这意味着一半的运行时间用于投射。这由 NVIDIA Nsight Systems 捕获,NVIDIA Nsight Systems 是一种分析工具,可在时间轴上可视化工作负载指标,以实现性能调优。
在图 2 的 CUDA 硬件行中:
- 前两个浅蓝色部分表示处理从
float32
到bfloat16
的投射的内核。 - 空白区域表示投射开销占总运行时间 400 微秒中的 200 微秒。
借助全半精度推理解决 AMP 开销问题
为了应对与 AMP 相关的挑战,我们通过完全以半精度(float16
或 bfloat16
)执行推理来实施最佳实践。这种方法如 NVIDIA/NeMo 在 GitHub 上的拉取请求中所述,可在不影响准确性的情况下消除不必要的投射开销,因为像 softmax
和 layer norm
这样的精度敏感型操作在后台仍使用 float32
,即使指定了半精度输入也是如此。请参阅 AccumulateType 和 SoftMax 示例。
您可以通过设置 compute_dtype=float16
或 compute_dtype=bfloat16
在 examples/asr/transcribe_speech.py
中启用此功能,同时确保未设置 amp=True
(默认值为 amp=False
)。同时设置 amp=True
和 compute_dtype
值将导致 错误 。如果您正在编写自己的 Python 代码,只需调用 model.to(torch.bfloat16)
或 model.to(torch.float16)
即可实现此优化,如 NeMo/examples/asr/transcribe_speech.py 所示。
优化批处理以提升性能
在 NeMo 中,某些操作最初是依次执行的,一次处理一个迷你批量的一个元素。这种方法导致速度减慢,因为每个内核操作在批量大小为 1 时运行得很快,但为每个元素启动 CUDA 内核的开销会导致效率低下。通过切换到全批量处理,我们充分利用了 GPU 流多处理器资源。
两个特定操作( CTC 贪婪解码 和 特征归一化 )受到此问题的影响。通过从顺序处理转向完全批量处理,我们将每次操作的吞吐量提高了 10%,总体速度提高了约 20%。
在解决了类似问题后, SpecAugment 的速度提高了 8-10 倍。(此操作仅在训练期间运行,因此这里不是重点。)
RNN-T 和 TDT 预测网络中的低计算强度
RNN-T 和 TDT 模型长期以来一直被认为不适合服务器端 GPU 推理,因为它们具有自回归预测和联合网络。例如,在 Parakeet RNN-T 1.1B 模型中,贪婪解码占用了总运行时间的 67%,尽管预测和联合网络仅占模型参数的不到 1%。
原因是?这些内核执行的任务很少,因此其性能完全受内核启动开销的限制,因此在大部分时间内 GPU 都处于空闲状态。例如,执行 CUDA 内核可能只需 1 到 3 微秒,而启动 CUDA 内核可能需要 5 到 10 微秒。在实践中,我们发现 GPU 空闲时间约为 80%,这表明消除这一空闲时间可以将推理速度提高 5 倍。
图 3 显示了 RNN-T 贪婪解码算法的几个“外部时间步长”的快照。CUDA HW 行包含多个空白(非蓝色)区域,表示没有执行 CUDA 代码的时间。由于算法中的每个外部时间步长对应于处理单个 80 毫秒的输入帧,因此运行 1.5 到 4.3 毫秒的速度慢得令人无法接受。
在图 3 的 CUDA 硬件行中,非蓝色区域表示何时未执行 CUDA 代码(GPU 处于空闲状态)。
通过 CUDA 图形条件节点中的动态控制流消除低计算强度
传统上,CUDA 图形用于消除内核启动开销。然而,它们不支持动态控制流,例如 if-else 循环,使得它们不适合直接用于贪婪解码。 CUDA 工具包 12.4 引入了 CUDA 图形条件节点 ,可启用动态控制流。
我们使用这些节点对 RNN-T 和 TDT 模型实施贪婪解码,有效消除了以下文件中的所有内核启动开销:
后两个文件实现了贪婪解码的标签循环变体,这将在下一节中讨论。
有关该问题和我们的解决方案的详细说明,请参阅我们的论文 《Speed of Light Exact Greedy Decoding for RNN-T Speech Recognition Models on GPU》。此外,我们还 向 PyTorch 提交了一个拉取请求 ,以支持在纯 PyTorch 中使用其新的 torch.cond
和 torch.while_loop
控制流 API 的条件节点,而无需与 CUDA API 进行任何直接交互。
RNN-T 和 TDT 预测网络的差异
执行批量 RNN-T 和 TDT 推理的一个重要问题是 vanilla 贪婪搜索算法的分歧。这种分歧会导致一些输入进展缓慢,而另一些则停滞不前,从而导致在使用更大批量大小时增加延迟。因此,许多实现选择批量大小为 1 的推理来避免此问题。但是,使用批量大小为 1 会导致硬件利用率不充分,这既低效又不经济。
常用于传感器解码的传统解码算法(图 4)采用了嵌套循环设计:
- 外循环:对帧(编码器输出)进行迭代。
- 内循环:逐个检索标签,直到遇到特殊的空白符号。
对于每个非空白符号,应更新自回归预测网络的隐藏状态和输出。在批量推理期间,内循环可以为批量中的不同发音生成不同数量的标签。因此,对于每帧,预测网络的调用次数由所有发音的非空白标签的最大数量决定,这是次优的。
图 4 展示了传统帧循环解码算法的示例,该算法分批处理两个词,每个词 4 帧,并进行 CAT 和 DOG 转录。∅ 表示批量解码中不必要的计算。
使用高效的新解码算法解决分歧
为了解决传统的帧循环解码算法问题,我们推出了一个新的标签循环算法 ,该算法仍使用嵌套循环,但区别在于循环的角色发生了交换(图 5)。
- 外循环:在标签上迭代,直到所有帧都已解码。
- 内循环:对帧进行迭代,识别批处理中每个语句的下一帧,其标签为非空白。这是通过推进指向当前编码器帧的索引来完成的,这些索引因批处理中每个语句而有所不同。
图 5 展示了新的标签循环解码算法的示例,该算法分批处理两个语句,每个语句 4 帧,CAT 和 DOG 转录。∅ 表示批量解码中不必要的计算。
在这种方法中,我们会在外循环的每个步骤上以尽可能大的批量大小评估预测网络。这种评估的数量恰好是所有句子中最长转录的长度(以令牌数量表示),这使其成为所需评估的最小数量。内循环仅使用联合网络执行操作。为了提高效率,我们在此过程的早期应用了编码器和预测网络投影,从而最大限度地减少了昂贵的重新计算需求。
这种批量标签循环算法显著提高了 RNN-T 和 TDT 网络的效率,即使使用纯 PyTorch 代码执行时无需额外的 GPU 特定优化,也能实现更快的解码速度。
性能提升速度提升高达 10 倍,成本效益提升高达 4.5 倍
标签循环和 CUDA 图形使传感器模型的逆实时系数(即 RTFx(生成音频的持续时间/计算时间;越高越好)比以往更接近 CTC 模型。这种影响在较小的模型中尤为明显,在这些模型中,减少内核启动开销(尤其是在涉及预测网络权重和输入张量等小数据大小的操作中)会带来更大的性能提升。此外,得益于新实施的向量化特征归一化解码实现,CTC 模型的速度有了显著提高。
在搭载 NeMo 2.0.0 的 NVIDIA NeMo ASR 型号中,所有这些速度提升高达 10 倍(图 1),可提供快速且经济高效的 CPU 替代方案。
为了更好地说明基于 ASR GPU 的推理的优势,我们估算了使用 CPU 和 AWS 等云平台上常见的 NVIDIA GPU 转录 100 万小时语音的成本,重点是计算优化的实例。在此比较中,我们使用了 NVIDIA Parakeet RNN-T 1.1B 模型。
- 基于 CPU 的估计: 对于 CPU 估计,我们在单个固定的 CPU 核心上运行批量大小为 1 的 NeMo ASR。这是一种常见的行业实践方法,允许跨多个核心进行线性扩展,同时保持恒定的 RTFx。我们选择了测量 RTFx 为 4.5 的 AMD EPYC 9454 CPU,可通过 Amazon EC2 C7a 计算优化实例获得。
- 基于 GPU 的估算: 对于 GPU , 我们使用了 Hugging Face Open ASR 排行榜的结果,该排行榜在 NVIDIA A100 80GB 上运行。等效的 AWS 实例为
p4de.24xlarge
,配备 8 个 NVIDIA A100 80GB GPU。 - 成本计算:为了计算 CPU 和 GPU 的总成本,我们:
- 将 100 万小时的语音除以相应的 RTFx。
- 四舍五入到最近的一个小时。
- 将结果乘以每小时实例成本。
如表 1 所示,从 CPU 切换到 GPU 进行 RNN-T 推理可节省高达 4.5 倍的成本。
CPU/GPU | AWS 实例 | 每小时成本 | vCPU/GPU 数量 | 每个实例的流数量* | RTFx (单台) |
总计 RTFx | 转录 100 万小时的成本 |
第四代 AMD Epyc | C7a.48 xlarge | 9.85 美元 | 192 | 192 | 4.5 | 864 | 11410 美元 |
NVIDIA A100 80GB | P4de.24 xlarge | 40.97 美元 | 8 | 512 | 2053 | 16425 | 2499 美元 |
*GPU 的 CPU 或全局批量大小
借助 NVIDIA ASR 加速转录
NVIDIA NeMo 可将 ASR 模型的性能提升高达 10 倍,在 Hugging Face Open ASR 排行榜上名列前茅。这一速度飞跃由自动投射到 bfloat16
的张量、标签循环算法和 CUDA Graphs 优化等创新提供动力支持。
这些加速性能还可显著节省成本。例如,与基于 CPU 的替代方案相比,基于 NVIDIA A100 的 NeMo GPU 驱动的推理在转录 100 万小时语音时可节省高达 4.5 倍的成本。
持续优化 NVIDIA Canary 1B 和 Whisper 等模型的努力将进一步降低运行注意力编码器 – 解码器和基于语音 LLM 的 ASR 模型的成本。NVIDIA 还在改进其 CUDA Graphs 条件节点,并将其与编译器框架 TorchInductor 集成,这将进一步加快 GPU 运行速度并提高效率。有关更多详情,请 查看我们的拉取请求,获取 PyTorch 中的条件节点支持 。
我们还发布了更小的 Parakeet 混合传感器-ctc 模型, Parakeet TDT CTC 10M ,可实现约 4,300 的 RTFx,并将 HF ASR 排行榜测试集的平均 WER 准确度提高到 7.5,进一步扩展了 NeMo ASR 的功能。
探索 NVIDIA NIM,用于语音和翻译 ,以更快、更具成本效益地将多语种转录和翻译集成到在云端、数据中心或工作站上运行的生产应用中。