AWS、NVIDIA MPSでEC2上のASR推論コストを75%削減
本文の状態
日本語全文を表示中
詳細モードで約19分の本文を読めます。
同じ出来事の情報源
この情報源を基点に整理
AWS Machine Learning Blog
従来の CUDA のデフォルト動作では ASR 推論時に GPU の約 80% がアイドル状態となるが、NVIDIA MPS を導入することで並列実行が可能になり、利用率を劇的に向上させる。
AI深層分析を開く2026年8月28日 01:52
AI深層分析
キーポイント
GPU 利用効率の課題と解決策
従来の CUDA のデフォルト動作では ASR 推論時に GPU の約 80% がアイドル状態となるが、NVIDIA MPS を導入することで並列実行が可能になり、利用率を劇的に向上させる。
インフラ要件の劇的削減
Heidi Health の実証では、GPU インスタンス数を 16 から 4 に減らすことに成功し、推論コストが 75% 削減された。
性能とレイテンシの維持
リソース削減後も、各 GPU あたり 92.1 RPS の処理能力を維持しつつ、サブ秒レベル(平均 650ms 未満)の低遅延要件を満たしている。
技術スタックの統合
NVIDIA Nemotron Parakeet TDT 0.6B V2 モデルを ONNX や TensorRT で最適化し、Triton Inference Server と MPS を組み合わせた構成が採用された。
MPSによるGPUリソースの効率化
CUDA MPSは複数のプロセスが1つのGPUコンテキストを共有し、異なるSM上でカーネルを同時に実行することでアイドル状態を削減する。これにより、従来の時間分割方式と比較してコンテキストスイッチのオーバーヘッドが除去される。
重要な引用
Reducing automatic speech recognition (ASR) inference costs on Amazon Elastic Compute Cloud (Amazon EC2) becomes critical when GPU utilization per request is low but latency requirements are strict.
This setup maintains sub-second latency at 92.1 requests per second (RPS) per GPU.
A single ASR inference request typically uses only 15–20 percent of a GPU’s compute capacity, yet the default time-slicing behavior in NVIDIA CUDA forces sequential access.
CUDA MPS funnels all CUDA work through a single GPU context managed by an MPS daemon process.
編集コメントを表示
編集コメント
医療現場での音声認識という実社会に直結するユースケースにおいて、技術的な最適化が明確なコスト削減と性能維持につながった事例は貴重である。特に GPU リソースの無駄をなくす MPS の活用方法は、リソース制約のある環境における AI 導入の重要な指針となる。
Source Article
元記事を日本語で読む
本文に関係しない購読案内、埋め込み通知、サイト内プロモーションは除いています。
本記事は、AWS と NVIDIA、そして Heidi による共同執筆です。
Amazon Elastic Compute Cloud (Amazon EC2) 上での音声認識(ASR)推論コストを削減することは、1 リクエストあたりの GPU 利用率が低くても、レイテンシ要件が厳しい場合に極めて重要になります。通常、1 つの ASR 推論リクエストで利用されるのは GPU の計算能力のわずか 15〜20% に過ぎませんが、NVIDIA CUDA® のデフォルトのタイムスライシング動作は順次アクセスを強制するため、ハードウェアの約 80% がアイドル状態となってしまいます。
Heidi Health は、190 カ国で週に 240 万件以上の臨床相談を処理する AI ケアパートナーです。ピーク時のトラフィックでも 1 秒未満のトランスクリプション遅延を実現するために、この非効率性を解消するためには、同社は 16 台の GPU インスタンスを稼働させる必要がありました。
以前の投稿 では、臨床用音声認識向けに Nemotron 音声モデル(NVIDIA Parakeet TDT 0.6B V2)をファインチューニングする方法をご紹介しました。今回の記事では、ファインチューニング後の「効率的なモデル提供」に焦点を当てます。具体的には、NVIDIA CUDA Multi-Process Service (MPS) と NVIDIA Triton Inference Server を組み合わせることで、コスト削減を実現する手法を実演します。

Amazon EC2 の GPU インスタンス上で NVIDIA MPS を利用することで、GPU インフラの要件を 75% 削減できます(16 インスタンスから 4 インスタンスへ)。この構成では、GPU あたり秒間 92.1 リクエスト(RPS)という高いスループットを維持しながら、レイテンシも 1 秒未満に抑えられています。
ソリューションの概要
ここでは、以下のトピックについて解説します。
- GPU 利用率が抱える課題
- NVIDIA ハードウェアで利用可能な 3 つの共有メカニズム
- ONNX と TensorRT を活用したモデルレベルの最適化
- Triton を用いたリクエストスケジューリング
- これらのコンポーネントが Amazon EC2 上でどのように統合されるか
GPU 利用率の問題
Parakeet TDT 0.6B V2 モデルに対して単一の ASR(自動音声認識)推論リクエストを実行すると、NVIDIA L40S GPU に搭載された 142 個のストリーミングマルチプロセッサ(SM)のうち、約 15〜20% が使用されるに過ぎません。フォワードパスの間、残りの 80% はアイドル状態のままです。
CUDA のデフォルトのタイムスライシング動作はこの非効率をさらに悪化させます。各プロセスが GPU を排他的に占有するため、プロセスは順番に実行され、コンテキストスイッチによるオーバーヘッドが発生します。結果として、並行実行は行われません。
その結果、単一の GPU で許容可能なレイテンシ(平均〜)を保ちながら処理できるのは、約 62 RPS(1 秒あたりのリクエスト数)に留まります。
この利用率のギャップを埋めるため、私たちは NVIDIA ハードウェアで利用可能な 3 つの GPU 共有メカニズムを検討しました。それぞれは、分離性、並行処理能力、運用上の複雑さの間で異なるトレードオフを持っています。
以下の図は、デフォルトの GPU タイムスライシング動作と CUDA MPS(Multi-Process Service)による並行実行を比較しています。MPS がアイドル状態にある SM 容量をどのように解消するかを示しています。

(図注:デフォルトの GPU タイムスライシングでは、各リクエストが SM の約 20% を使用し、16 台の GPU にわたって 80% がアイドル状態になるのに対し、CUDA MPS では 4 台の GPU でそれぞれ 25% の SM を持つ 4 つの並行インスタンスを実行します。)
図 1:GPU のタイムスライシングと CUDA MPS の比較。左側はデフォルトのタイムスライシングで、各リクエストが SM(ストリーミングマルチプロセッサ)の約 20% しか使用せず、残りの 80% がアイドル状態となり、コンテキストスイッチのオーバーヘッドも発生するため、16 台の GPU が必要になります。右側は CUDA MPS で GPU を 4 つの並行インスタンスに分割し、各インスタンスが SM の 25% を使用することで、4 台の GPU で 92.1 RPS を達成し、GPU 数を 75% 削減しています。
GPU 共有の仕組み:タイムスライシング、MIG、そして MPS
NVIDIA GPU には、マルチテナント環境での共有を実現する 3 つのメカニズムがあります。それぞれに異なるトレードオフが存在します。
| 仕組み | 分離 | 並行実行 | 最適な用途 |
|---|---|---|---|
| タイムスライシング(デフォルト) | 完全なコンテキストスイッチ | なし — 逐次実行 | 少数の大規模モデル |
| MIG (Multi-Instance GPU) | ハードウェアによる物理的パーティション化 | あり — 固定パーティション | マルチテナント分離 |
| MPS (Multi-Process Service) | 共有コンテキスト、ソフトな SM リミット | あり — 並行カーネル | 1 つの GPU 上の多数の小規模モデル |
NVIDIA CUDA MPS は、CUDA API とバイナリ互換性を持つ代替実装です。これにより、コード変更なしで複数のプロセスが GPU を同時に共有できます。時間スライシング(プロセスが順次アクセスを切り替える方式)や、専用メモリコントローラーを持つ物理的なハードパーティションを作成する Multi-Instance GPU (MIG) とは異なり、MPS はすべての CUDA 処理を MPS デーモンプロセスが管理する単一の GPU コンテキストに集約します。
当社のワークロードにおける主な利点は以下の通りです。
- コンテキストスイッチのオーバーヘッドを排除:全プロセスで GPU のスケジューリングリソースを共通化できます。
- 並列カーネル実行に対応:異なるプロセスからのカーネルが、異なる SM(ストリーミングマルチプロセッサ)上で同時に実行されます。
- CUDA_MPS_ACTIVE_THREAD_PERCENTAGE 環境変数によるパーティションサイズの調整が可能。
- コード変更不要:既存の CUDA アプリケーションはそのまま動作します。
- 別々のアドレス空間を用いたクライアント間のメモリ保護機能。
今回のワークロードでは、専用 GPU インスタンス上で 2 つの MPS 設定をそれぞれデプロイします。文字起こし用インスタンスでは SM の 25% を割り当て、4 つのプロセスを並列実行(各プロセスは 48 GB の VRAM から約 2.5 GB を使用)します。話者分離用インスタンスでは SM の 12% を割り当て、8 つのプロセスを並列実行(各プロセスは約 1.8 GB を使用)します。
MPS は GPU 利用率の向上に寄与しますが、リクエストあたりの計算時間をさらに削減するにはモデルレベルでの最適化も必要です。次の最適化層では、計算負荷の高いエンコーダーをハードウェア最適化された形式に変換します。
ONNX Runtime with TensorRT
ONNX Runtime は、ハードウェア固有の Execution Provider を活用して Open Neural Network Exchange (ONNX) モデルを実行する高性能な推論エンジンです。TensorRT Execution Provider は ONNX グラフノードを NVIDIA TensorRT にルーティングし、カーネル融合や精度キャリブレーション(FP16/INT8)、メモリ最適化を適用することで、ハードウェアに最適化されたエンジンを生成します。
今回のワークロードでは、ハイブリッドなアプローチを採用しています。計算負荷の高い Conformer エンコーダー(24 レイヤー、隠れ層 1024)は ONNX Runtime を介して実行され、TensorRT EP の恩恵を受けて演算子の融合と FP16 精度キャリブレーションを享受します。一方、RNN-T Token-and-Duration Transducer (TDT) デコーダーは PyTorch CUDA でネイティブに動作し、静的な TensorRT エンジンよりも柔軟性が高い CUDA グラフキャッシングを活用した可変長トークンの生成を実現しています。
NVIDIA Triton Inference Server
NVIDIA Triton Inference Server は、本番環境での推論におけるリクエストスケジューリングとバッチ処理を担当します。パイプラインでは以下の 2 つのバッチ戦略を使用しています。
- ダイナミックバッチング(文字起こし): 設定可能な遅延時間(50 ms)の間リクエストを蓄積し、まとめてバッチとして送信します。推奨されるバッチサイズ [4, 8, 16] を用いることで、スケジューラーが最適なグループを形成できます。
- シーケンスバッチング(話者分離): サーバー側で録音ごとのストリーミング状態を維持します。各クライアントは相関 ID を付与した 15 秒間の音声チャンクを送信し、Triton がそれを適切なモデルインスタンスへルーティングします。セッションは 600 秒のアイドル時間(max_idle_timeout)が経過すると自動的に期限切れになります。
各Tritonモデルインスタンスは1つのMPSパーティションにマッピングされるため、バッチスケジューラとGPUパーティショニング層の間に自然な統合が実現されます。
これら3つの技術はAmazon EC2上で統一された推論パイプラインを構成し、以下でその概要を説明します。
推論パイプラインのアーキテクチャ
本推論パイプラインは、Amazon EC2のg6e.4xlargeおよびg7e.4xlargeインスタンス(NVIDIA L40S、VRAM 48 GB)上で動作し、Docker Composeでオーケストレーションされた3つのコンテナ化されたコンポーネントで構成されています。
以下の図は、単一のAmazon EC2 GPUインスタンス上に展開される3層構造の推論アーキテクチャを示しています。

**図 2: Amazon EC2上のソリューションアーキテクチャ。FastAPIゲートウェイが音声データをデコードし、gRPCを介してTriton Inference Serverへリクエストをルーティングします。同サーバーはMPSパーティション化されたモデルインスタンス間で負荷分散を行います。
3つのレイヤーの詳細は以下の通りです。
FastAPIゲートウェイ: OpenAI Whisperと互換性のあるREST APIで、アップロードされた音声データを16 kHzモノラルのfloat32テンソルに変換後、gRPCを介してTritonへ転送します。ポート8002上で4つのuvicornワーカーを実行しています。
NVIDIA Triton Inference Server:トランスクリプションでは動的バッチ処理(推奨バッチサイズは [4, 8, 16]、最大キュー遅延時間は 50000 マイクロ秒)を管理し、ストリーミングのダイアライゼーションではシーケンスバッチ処理を行います。複数のモデルインスタンス間でリクエストを分散します。
CUDA MPS daemon:推論サーバー起動前に Triton コンテナ内で起動し、GPU を並行実行コンテキストに分割します。トランスクリプションの場合は 4 インスタンス(SM の 25% ずつ)、ダイアライゼーションの場合は 8 インスタンス(SM の 12% ずつ)を割り当てます。
AWS サポートサービス:
- Amazon Elastic Container Registry (Amazon ECR):Triton とゲートウェイのコンテナイメージを保存します(ベースイメージは nvcr.io/nvidia/tritonserver:26.03-py3)。
- Amazon Elastic Block Store (Amazon EBS):モデルのチェックポイント、TensorRT エンジンのキャッシュ、ONNX 出力ファイルを保存します。
- Amazon CloudWatch:Prometheus メトリクスの取り込み、ログ集約、p50/p90/p95/p99 のレイテンシダッシュボードを提供します。
- Amazon Simple Storage Service (Amazon S3):モデルアーティファクトのアーカイブとチェックポイント保存用ストレージです。
事前準備
以下の項目は、付随するリポジトリを前提としています。これらが揃っていれば、後述のデプロイ手順に従って進めることができます。
- Amazon EC2 の g6e.4xlarge または g7e.4xlarge インスタンス(NVIDIA L40S、VRAM 48 GB)にアクセスできる AWS アカウント。
- NVIDIA ドライバ 535 以上と CUDA 12.x。
- Docker と NVIDIA Container Toolkit。
NVIDIA Triton Inference Server コンテナ (nvcr.io/nvidia/tritonserver:26.03-py3)
NVIDIA NeMo Toolkit 2.7 以上と、Parakeet TDT 0.6B V2 モデルのチェックポイント (.nemo フォーマット)。
音声デコーディングには torchcodec を使用します (pip install torchcodec)。
ゲートウェイから Triton への通信には tritonclient[grpc] を利用します。
実装の詳細
本記事に付随するオープンソースリポジトリには、完全な実装コードが含まれています。以下のセクションでは、CUDA MPS 環境下での安定した動作を実現するためのデプロイ手順、設定方法、そして重要な設計判断について解説します。このリポジトリには、推論パイプラインの構築と展開に必要な Dockerfile、Triton モデルバックエンド、FastAPI ゲートウェイ、オーケストレーション設定などがすべて揃っています。
付随するリポジトリをクローンし、以下の 3 つのコマンドでデプロイします:
# 1. Build (provide your fine-tuned .nemo checkpoint)
docker build -f Dockerfile.single \
--build-arg LOCAL_NEMO_FILENAME=your_model.nemo \
-t parakeet-mps:latest .
# 2. Run with 4 concurrent instances on one GPU
docker run --gpus all --shm-size=2g \
-e MPS_INSTANCE_COUNT=4 \
-p 8002:8002 \
parakeet-mps:latest
# 3. Transcribe (OpenAI Whisper-compatible API)
curl -X POST http://localhost:8002/v1/audio/transcriptions \
-F file=@audio.wav -F model=parakeet-tdtコンテナは MPS デーモンの起動、モデルの読み込み、ヘルスモニタリングを自動的に処理します。サービスが準備完了すると、/health エンドポイントからステータスコード 200 が返されます (通常、起動から 90〜120 秒後です)。完全なクイックスタートガイドについては、リポジトリの README を参照してください。
リポジトリの探索
このリポジトリでは、2 つのデプロイモードをサポートしています。1 つ目は単一のオールインワンコンテナ (Dockerfile.single) です。2 つ目は Docker Compose による 2 コンテナ構成で、GPU 推論層と CPU ゲートウェイ層を独立してスケールさせることができます。
├── Dockerfile.single # All-in-one: MPS daemon + Triton + gateway
├── Dockerfile.triton # Triton-only (GPU container)
├── Dockerfile.gateway # Gateway-only (CPU container)
├── docker-compose.yml # Two-container orchestration
├── start-single-container.sh # Single-container entrypoint
├── auto_config.py # MPS instance count -> Triton config
├── server.py # FastAPI gateway (OpenAI-compatible API)
└── triton_model_repo/
└── parakeet_asr/
├── config.pbtxt # Dynamic batching configuration
└── 1/model.py # Python backend - direct forward passコンテナのビルドと実行
微調整済みの .nemo チェックポイントをビルド引数として使用してコンテナイメージを構築し、必要な MPS インスタンス数で実行します。Dockerfile はチェックポイントをイメージに埋め込み込み、ビルドステップ中にローカルアテンション最適化を適用します。
# Build the all-in-one image
docker build -f Dockerfile.single \
--build-arg LOCAL_NEMO_FILENAME=your_model.nemo \
-t parakeet-mps:latest .
# Run with 4 MPS instances (25% SM each) on a single GPU
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)が、すべてのランタイム動作を制御します。同じコンテナイメージは、GPU タイプに関わらず MPS_INSTANCE_COUNT を変更することで使用可能です。この設定により、Triton インスタンスグループの数と各インスタンスあたりの SM パーセントが同時に決定されます。完全な設定リファレンスについては、リポジトリの README を参照してください。
重要な設計判断の理解
本実装では、CUDA MPS の下で安定して動作させるために不可欠な、いくつかの重要な設計判断を行っています。このセクションではその中でも特に重要なものを解説します。
直接フォワードパスの実行。 Triton バックエンドは NeMo を介して model.transcribe() を呼び出すのではなく、model.forward() を直接呼び出します。これにより、リクエストあたり約 50 ミリのフレームワークオーバーヘッドが削減されます。bfloat16 autocast と各インスタンス専用の CUDA ストリームを組み合わせることで、単一のインスタンスで 45 秒のオーディオを約 160 ミリ秒で処理できます。
モデルのシリアライズ読み込み
6 億パラメータのモデルを 4 つのプロセスで同時に読み込むと、GPU メモリが不足します。このためバックエンドはファイルロック(fcntl.flock)を用いて初期化を直列化し、各インスタンスは順に読み込み、GPU に転送し、重みを凍結し、CUDA グラフのウォームアップを実行してからロックを解放します。
CUDA グラフのウォームアップ範囲
TDT デコーダーではカーネル起動オーバーヘッドを削減するため CUDA グラフを利用しています。初期化時にバックエンドは、想定される本番環境での形状(バッチサイズ 1 で 5, 15, 30, 45, 60 秒、およびバッチサイズ 2 で 61 秒)をすべてウォームアップします。この範囲内の形状ではキャッシュされたグラフが再利用され、約 165 ms で処理されます。これを超える形状の場合、その呼び出し限りでイーグゼクション(実行モード)にフォールバックし、約 500 ms かかります。
MPS 対応の CUDA グラフフォールバック
MPS 環境下では、NeMo のデコーダーが新しいテンソル形状に出会うと CUDA グラフの再キャプチャを試みます。しかし、再キャプチャに要する 1.5〜2.5 秒の間に、同じ MPS に属す他のインスタンスが干渉してキャプチャを破損させ、cudaErrorIllegalAddress エラーが発生しプロセスがクラッシュします。
ウェッジ(動作停止)検知によるヘルスモニタリング
負荷が持続すると、ある MPS インスタンスで CUDA エラーが発生しても回復不能になることがあります。バックエンドは CUDA ストリームプローブの失敗を通じて「ウェッジした」インスタンスを検出すると、/tmp/parakeet_wedged へ sentinel ファイルを tmpfs に書き込みます。
動的バッチング
Triton は最大バッチサイズ 16(推奨サイズは 4, 8, 16)までリクエストを蓄積し、最大キュー遅延を 50 ms に設定することで、レイテンシとスループットのバランスを取ります。
ゲートウェイ側での音声デコード
FastAPI ゲートウェイは torchcodec を用いて WAV、WebM/Opus、MP3、M4A、FLAC 形式の音声デコードを処理します。これにより、Triton への入力データは生の float32 テンソルとして保持され、ゲートウェイ側では CPU のみで動作が可能になります。
ストリーミング話者分離(ダイアライゼーション)
話者分離モデル「NVIDIA Streaming Sortformer 4-speaker v2」は、12% の SM を各インスタンスに割り当てた MPS インスタンスを 8 つ使用し、録音ごとの状態管理のためにシーケンスバッチ処理を行います。各録音にはチャンクルーティング用の一意な相関 ID が付与され、セッションは 600 秒後に自動的に期限切れとなります。このモデルは、コンテナ起動時のウォームアップ最適化を施した TensorRT + ONNX エンジンとして実行されます。
API エンドポイント
ゲートウェイは OpenAI Whisper と互換性のある API(POST /v1/audio/transcriptions)を提供し、既存の統合システムへの差し替えが容易です。その他のエンドポイントには、死活監視とウェッジセントリーチェックを行う /health、Prometheus 形式のレイテンシ四分位数を出力する /metrics などがあります。レスポンスフォーマットは json、verbose_json、text、srt、vtt をサポートしています。詳細な API リファレンスについてはリポジトリをご参照ください。
結果
ベンチマークでは、各構成で並行処理数を 1 から 100 まで変化させ、5 回の測定を平均化しました。使用した音声サンプルは、臨床相談の典型的なセグメントです。SLA の閾値は以下の通りです。
Conc
RPS
RPM
p50 (ms)
Mean (ms)
p99 (ms)
SLA
1
6.3
376
161.1
161.1
164.2

4
今日のまとめ
AIデイリーブリーフで今日の重要ニュースをまとめ読み