在 Amazon EC2 GPU 实例上,NVIDIA CUDA 多进程服务(MPS)配合 Triton 推理服务器,可将语音识别(ASR) GPU 基础设施削减 75%,同时保持亚秒级延迟和 92.1 QPS/GPU 吞吐量。
本文由 AWS、NVIDIA 和 Heidi 联合撰写。
当每个请求的 GPU 利用率较低但延迟要求严格时,降低 Amazon Elastic Compute Cloud(Amazon EC2)上自动语音识别(ASR)推理成本变得至关重要。单个 ASR 推理请求通常仅使用 GPU 计算容量的 15%–20%,而 NVIDIA CUDA® 的默认时间分片行为强制顺序访问,导致 80% 的硬件处于空闲状态。Heidi Health 是一个 AI 护理合作伙伴,每周在 190 个国家/地区处理超过 240 万次临床咨询。为了在高流量时保持亚秒级转录延迟,这种低效性迫使该公司运行 16 个 GPU 实例。
在之前的文章中,您学习了如何微调 Nemotron 语音模型 NVIDIA Parakeet TDT 0.6B V2 以进行临床语音识别。在本文中,我们专注于微调之后的环节:高效地服务该模型。我们演示了 NVIDIA CUDA Multi-Process Service(MPS)如何与 Amazon EC2 GPU 实例上的 NVIDIA Triton Inference Server™ 相结合,将 GPU 基础设施需求降低 75%(从 16 个实例减少到 4 个)。此配置在每 GPU 92.1 请求/秒(RPS)下保持亚秒级延迟。
本节涵盖以下内容:
在 Parakeet TDT 0.6B V2 模型上,单个 ASR 推理请求仅使用 NVIDIA L40S GPU 142 个流式多处理器(SM)中约 15%–20% 的计算能力。在每次前向传递期间,剩余 80% 处于空闲状态。CUDA 的默认时间分片行为通过给每个进程独占 GPU 访问权来加剧这种浪费。进程轮流使用 GPU,在它们之间添加上下文切换开销,并且不发生并发执行。
结果是:单个 GPU 在可接受的延迟(平均 < 650 ms,p99 < 1,000 ms)下只能处理约 62 RPS。这要求 Heidi 当前的生产部署中使用 16 个 GPU 来处理峰值流量,并为延迟服务级别协议(SLA)留出足够的余量。
为了解决这一利用率差距,我们评估了 NVIDIA 硬件上可用的三种 GPU 共享机制,每种机制在隔离、并发和操作复杂性之间有不同的权衡。
下图比较了默认 GPU 时间分片行为与 CUDA MPS 并发执行,展示了 MPS 如何消除空闲 SM 容量。
图 1:GPU 时间分片与 CUDA MPS 对比。左侧:默认时间分片,每个请求仅使用约 20% 的 SM,约 80% 处于空闲状态并产生上下文切换开销,需要 16 个 GPU。右侧:CUDA MPS 将 GPU 划分为 4 个并发实例,每个占用 25% 的 SM,仅用 4 个 GPU 就实现了 92.1 RPS(减少 75%)
NVIDIA GPU 提供三种多租户共享机制,每种机制在隔离、并发和操作复杂性之间有不同的权衡:
NVIDIA CUDA MPS 是 CUDA API 的二进制兼容替代实现。它允许多个进程并发共享 GPU 而无需代码更改。与时间分片(进程轮换访问)或多实例 GPU(MIG,创建具有专用内存控制器的硬物理分区)不同,MPS 通过单个 MPS 守护进程管理的 GPU 上下文汇聚所有 CUDA 工作。
对于我们的工作负载,主要优势包括:
CUDA_MPS_ACTIVE_THREAD_PERCENTAGE 环境变量配置分区大小对于此工作负载,在专用 GPU 实例上部署两种独立的 MPS 配置。转录实例使用 25% 的 SM 分配,包含 4 个并发进程(每个使用约 48 GB VRAM 中的 2.5 GB)。说话人分离(diarization)实例使用 12% 的 SM,包含 8 个并发进程(每个约 1.8 GB)。
尽管 MPS 解决了 GPU 利用率问题,我们可以通过模型级优化进一步减少每次请求的计算时间。我们优化堆栈的下一层将模型的计算密集型编码器转换为硬件优化格式。
ONNX Runtime 是一个高性能推理引擎,使用硬件特定的执行提供程序运行 Open Neural Network Exchange(ONNX)模型。TensorRT 执行提供程序将 ONNX 图节点路由到 NVIDIA TensorRT,后者应用内核融合、精度校准(FP16/INT8)和内存优化,以生成硬件调优引擎。
对于我们的工作负载,流水线采用混合方法。计算密集型 Conformer 编码器(24 层,1024 隐藏维度)通过带 TensorRT EP 的 ONNX Runtime 运行,受益于算子融合和 FP16 精度校准。RNN-T Token-and-Duration Transducer(TDT)解码器在 PyTorch CUDA 中原生运行,其中可变长度令牌生成与 CUDA 图缓存比静态 TensorRT 引擎更灵活。
NVIDIA Triton Inference Server 负责生产推理的请求调度和批处理。流水线使用两种批处理策略:
max_idle_timeout)每个 Triton 模型实例映射到一个 MPS 分区,在批处理调度器和 GPU 分区层之间提供自然的集成。
这三种技术组合成 Amazon EC2 上的统一推理流水线,下节将详细描述。
推理流水线在 Amazon EC2 g6e.4xlarge 和 g7e.4xlarge 实例(NVIDIA L40S,48 GB)上运行,包含三个容器化组件,使用 Docker Compose 进行编排:
下图展示了部署在单个 Amazon EC2 GPU 实例上的三层推理架构。
图 2:Amazon EC2 上的解决方案架构。FastAPI 网关解码音频并通过 gRPC 将请求路由到 Triton Inference Server,后者跨 MPS 分区的模型实例分派请求
三层架构如下:
FastAPI 网关:OpenAI Whisper 兼容的 REST API,将上传的音频解码为原始 16 kHz 单声道 float32 张量,然后通过 gRPC 转发到 Triton。在端口 8002 上运行 4 个 uvicorn worker。
NVIDIA Triton Inference Server:管理转录的动态批处理(首选批次大小 [4, 8, 16],max_queue_delay_microseconds: 50000)和流式说话人分离的序列批处理。跨模型实例分派请求。
CUDA MPS 守护进程:在推理服务器之前在 Triton 容器内启动。将 GPU 分区为并发执行上下文(转录用 4 个实例,每个占用 25% SM;说话人分离用 8 个实例,每个占用 12% SM)。
支持 AWS 服务:
nvcr.io/nvidia/tritonserver:26.03-py3 基镜像)以下前提条件适用于配套代码库。具备这些条件后,您可以按照后续部分的部署步骤进行操作。
nvcr.io/nvidia/tritonserver:26.03-py3).nemo 格式)torchcodec 用于音频解码(pip install torchcodec)tritonclient[grpc] 用于网关到 Triton 的通信本文附带的开源代码库提供了完整的实现。以下部分将逐步介绍部署、配置以及在 CUDA MPS 下稳定运行的关键设计决策。该代码库包含构建和部署推理流水线所需的一切:Dockerfile、Triton 模型后端、FastAPI 网关和编排配置。
使用三条命令克隆附带代码库并进行部署:
构建并运行容器
使用微调后的 .nemo 检查点作为构建参数构建容器镜像,然后以所需的 MPS 实例数运行。Dockerfile 将检查点 baked 到镜像中,并在构建步骤期间应用局部注意力优化。
# 构建一体化镜像
docker build -f Dockerfile.single \
--build-arg LOCAL_NEMO_FILENAME=your_model.nemo \
-t parakeet-mps:latest .
# 在单块 GPU 上以 4 个 MPS 实例运行(每个占 25% SM)
docker run --gpus all --shm-size=2g \
-e MPS_INSTANCE_COUNT=4 \
-p 8002:8002 \
parakeet-mps:latest
容器启动顺序为:(1) 启动 CUDA MPS 守护进程,(2) 运行 auto_config.py 设置 Triton 实例数和 SM 百分比,(3) 启动 tritonserver。完整的构建和运行说明请参考仓库。
配置部署
环境变量(MPS_INSTANCE_COUNT、GATEWAY_WORKERS、TRITON_URL、CUDA_VISIBLE_DEVICES)控制所有运行时行为。同一容器镜像通过更改 MPS_INSTANCE_COUNT 即可在不同 GPU 类型上工作,该变量同时设置 Triton 实例组数量和每个实例的 SM 百分比。完整配置参考请参考仓库 README。
理解关键设计决策
该实现在 CUDA MPS 稳定运行下做出了几个重要的设计选择。本节重点介绍其中最关键的部分。
直接前向传递。Triton 后端直接调用 model.forward() 而非通过 NeMo 调用 model.transcribe(),消除了每个请求约 50 ms 的框架开销。结合 bfloat16 autocast 和每个实例专用的 CUDA stream,单个实例处理 45 秒音频约需 160 ms。
序列化模型加载。四个进程同时加载一个 600M 参数模型会超出 GPU 显存。后端使用文件锁(fcntl.flock)序列化初始化,每个实例依次加载、移动到 GPU、冻结权重、执行 CUDA graph 预热后再释放锁。
CUDA graph 预热范围。TDT 解码器使用 CUDA graphs 消除内核启动开销。在初始化期间,后端预热所有预期的生产形状(batch size 为 1 时的 5、15、30、45 和 60 秒,加上 batch size 为 2 时的 61 秒)。此范围内的形状以约 165 ms 的速度重放缓存的 graphs。超出范围的形状回退到 eager 执行(约为 500 ms),仅在该次调用时生效。
MPS 安全的 CUDA graph 回退。在 MPS 下,当 NeMo 的解码器遇到新的 tensor 形状时,会尝试重新捕获 CUDA graph。在 1.5–2.5 秒的重新捕获窗口期间,兄弟 MPS 实例会破坏捕获,导致 cudaErrorIllegalAddress 并使进程崩溃。
楔形哨兵健康监控。在持续负载下,一个 MPS 实例中的 CUDA 错误可能导致其无法恢复。当后端检测到楔形实例(通过 CUDA stream 探测失败)时,会向 tmpfs(/tmp/parakeet_wedged)写入一个哨兵文件。
动态批处理。Triton 将请求累积到 batch size 16(首选大小为 4、8、16),最大队列延迟为 50 ms,在延迟和吞吐量之间取得平衡。
网关侧音频解码。FastAPI 网关使用 torchcodec 处理音频解码(WAV、WebM/Opus、MP3、M4A、FLAC),保持 Triton 输入为原始 float32 tensors,使网关可以在纯 CPU 节点上运行。
流式说话人分离
说话人分离模型(NVIDIA Streaming Sortformer 4-speaker v2)使用八个 MPS 实例,每个占 12% SM,并使用序列批处理来维护每条录音的状态。每条录音获得一个唯一的关联 ID 用于分块路由,会话在 600 秒后自动过期。该模型作为 TensorRT + ONNX 引擎运行,并在容器启动时进行预热优化。
网关提供 OpenAI Whisper 兼容的 API(POST /v1/audio/transcriptions),可作为现有集成的直接替代品。其他端点包括 /health(存活探针 + 楔形哨兵检查)和 /metrics(Prometheus 格式的延迟分位数)。响应格式包括 json、verbose_json、text、srt 和 vtt。完整 API 参考请参考仓库。
基准测试对每个配置从 1 到 100 的并发进行扫描,取 5 轮测量的平均值。音频样本为具有代表性的临床会诊片段。SLA 阈值为:平均延迟 < 650 ms 且 p99 < 1,000 ms。
配置 1:Triton + MPS(g6e.4xlarge)
⬅ 最优运行点——最后一个满足平均延迟 < 650 ms 且 p99 < 1,000 ms 的并发数。
结果:推荐 4 块 GPU(相比目前的 16 块),减少 75%。
配置 2:Triton + MPS(g7e.4xlarge)—— 选定的生产路径
与 g6e 相比,g7e 在最优运行点实现了超过 51% 的吞吐量提升和低于 25% 的延迟降低。
结果:推荐 4 块 GPU(相比目前的 16 块),减少 75%。
配置 3:TensorRT + ONNX + MPS
结果:推荐 2 块 GPU(相比目前的 16 块),减少 88%。
配置对比
下图比较了所有配置的吞吐量扩展情况。寻找每条线进入 SLA 违规区域(虚线区域)的交叉点,这决定了每个配置的最大可持续并发数。

我们在 TensorRT 引擎预热优化前后对说话人分离模型进行了基准测试:
预热优化还将标准差从 12.62 ms 降低到 7.13 ms(降低超过 44%),表明推理延迟具有更高的可预测性。该模型将 60 秒录音分成四个 15 秒的块处理,所有块都在整体管道预算范围内。
从运营角度来说,说话人分离以每块 238 ms 的平均延迟处理 60 秒会诊(总计低于 1 秒,实时因子 0.016x)。八个说话人分离实例运行在与转录独立的 MPS 分区上,无资源竞争。
测试完成后,为避免产生持续费用,请清理按照本文操作时创建的资源:
停止并终止 Amazon EC2 GPU 实例(g6e.4xlarge 或 g7e.4xlarge)。
删除附加的 Amazon EBS 卷(模型检查点、TensorRT 缓存)。
如果已推送到 Amazon ECR,请从中删除 Docker 镜像。
删除测试期间创建的任何 Amazon CloudWatch 日志组。
在本文中,我们展示了 Amazon EC2 上的 NVIDIA CUDA MPS 如何在保持亚秒级延迟 SLA(平均延迟 < 650 ms,p99 < 1,000 ms)的同时,将 ASR 推理基础设施减少 75%(从 16 块 GPU 降至 4 块)。在 g7e.4xlarge 上,MPS 以 352 ms 的平均延迟实现每 GPU 92.1 RPS。TensorRT + ONNX + MPS 优化进一步提升至 111.6 RPS(减少 88%),适用于在每个微调周期可接受 ONNX 重新导出的工作负载。
这些优化方法与模型无关:MPS 架构、直接前向传递模式、CUDA Graph 安全机制和 wedge sentinel 适用于任何通过 Triton 在 NVIDIA GPU 上服务的 encoder-decoder 模型。同样的方法已在 NVIDIA Canary 和 OpenAI Whisper large-v3 权重上验证通过。该模式可扩展到任何单个请求只占用可用 GPU 算力一小部分的工作负载。
对于生产部署,先在 g7e.4xlarge 上启动四个 MPS 实例,然后用 nvidia-smi 监控 GPU SM 利用率。如果 p99 延迟还有余量,就逐步增加 MPS_INSTANCE_COUNT。TensorRT + ONNX + MPS 路径可额外提升 21% 的吞吐量(从 92.1 RPS 提升到 111.6 RPS)。代价是部署流水线更长,需要每周重新导出 ONNX。
附带的 GitHub 仓库包含完整的实现:Dockerfile、Triton 模型配置、FastAPI 网关、CUDA Graph 安全补丁、健康监控以及基准测试脚本,可在任何 EC2 GPU 实例上直接部署。
要开始使用,请浏览以下资源:
附带的 GitHub 仓库,包含完整实现。
Amazon EC2 G6e 和 G7e 实例。
NVIDIA Triton Inference Server 文档。
第一部分:在 Amazon EC2 上微调 NVIDIA NeMoTron Speech ASR 以进行领域适配。
作者感谢以下 AWS 和 Heidi 团队成员对本文的贡献:Faisal Masood、Prem Oommen、Xuetong Wu、Taha Ansari 和 Ocha Cakramurti。