NVIDIA MPS徹底解説
■ MPSとは
-
目的: 複数の CUDA プロセスが 1 枚の GPU を“同時に”使い、SM(Streaming Multiprocessor)を共有することで GPU 利用効率とスループットを向上 させるランタイムサービス。
-
アーキテクチャ:
- MPS デーモン (nvidia‑cuda‑mps‑control) がクライアント各プロセスのドライバ呼び出しを受け取り、単一の GPU コンテキスト内でマルチプレクス。
- 低レイテンシな Unix ドメインソケット によりユーザー空間でスケジューリング。
-
メリット:
- コンテキスト切替コストの削減。
- スループット型ワークロード(小規模カーネルが頻繁に発火)での飽和。
- GPU 単位のライセンス/コストを抑えつつ複数ジョブを同居。
-
制限:
- 同一 Linux ユーザー 内プロセスのみ同居可。
- メモリは 早い者勝ち。
CUDA_MPS_ACTIVE_THREAD_PERCENTAGE
は SM 制御のみでメモリ割当は行わない。 - MIG 非対応 GPU (RTX/Ada 系など) でのみ選択肢となる。
■ MPSの設定方法
-
前提: CUDA 11 以降 & ドライバ 450+、Compute Capability ≥ 3.5。
-
環境変数
export CUDA_VISIBLE_DEVICES=0 # 利用 GPU を固定 export CUDA_MPS_PIPE_DIRECTORY=/tmp/mps # ソケット置き場 export CUDA_MPS_LOG_DIRECTORY=/tmp/mps/log # ログ置き場 export CUDA_MPS_ACTIVE_THREAD_PERCENTAGE=50 # 各プロセス最大 SM 使用率
-
デーモン起動/停止
nvidia-cuda-mps-control -d # 起動 echo quit | nvidia-cuda-mps-control # 停止
-
Docker Compose 例 (同一 GPU 共有)
services: worker_a: image: ml-app environment: - NVIDIA_VISIBLE_DEVICES=0 worker_b: image: ml-app environment: - NVIDIA_VISIBLE_DEVICES=0
コンテナ数=MPS クライアント数 となり、起動順にソケットへ接続。
-
監視:
watch -n1 nvidia-smi pmon -c 1
で SM/メモリ使用率を確認。
■ MPSの図解(code block)
──────────────────────────── ❶ MPS なし(時間分割) ────────────────────────────
時間 ───────▶
┌───────────────────────────────────────────────────────────────┐
│ GPU Execution Units (SM 群): │
│ │
│ ┏━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┓ │
│ ┃ Proc A ┃ Proc B ┃ … │
│ ┗━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━┛ │
│ t0────────t1 t1────────t2 │
│ (この区間は GPU 全体を A が占有) │
└───────────────────────────────────────────────────────────────┘
──────────────────────────── ❷ MPS あり(同時並列実行) ─────────────────────────
時間 ───────▶ ※ 同じ幅=同じクロック区間
┌───────────────────────────────────────────────────────────────┐
│ GPU Execution Units (SM 群): │
│ │
│ ┏━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┓ │
│ ┃ A │ B ┃ A │ B ┃ B │ C ┃ … ← 同じ瞬間に複数プロセス │
│ ┗━━━━━━━━━┻━━━━━━━━━┻━━━━━━━━━┛ │
│ t0────────t1 t1────────t2 t2────────t3 │
│ (SM を A と B が半分ずつ共有) │
│ (次スライスでは B と C が共有) │
└───────────────────────────────────────────────────────────────┘
■ MPSアーキテクチャ(OSレベル図)
+-----------------------------------------------------------+
| User Space |
| +-----------------------------------+ +--------------+ |
| | CUDA Application A (libcudart.so) | | App B ... | |
| +-----------------------------------+ +--------------+ |
| ▲ CUDA Driver API (libcuda.so) |
+-----------------------│----------------------------------+
│ Unix Domain Sockets (IPC)
+-----------------------▼----------------------------------+
| MPS Control Daemon (mps‑control) |
+-----------------------▲----------------------------------+
│ ioctl / NV_IOCTL
+-----------------------▼----------------------------------+
| Kernel Space (nvidia, nvidia_uvm) |
+-----------------------▲----------------------------------+
│ PCIe / NVLink
+-----------------------▼----------------------------------+
| GPU Hardware (SMs, VRAM) |
+-----------------------------------------------------------+
■ MPSの想定ユースケース
-
小規模カーネルが大量発生する推論サーバ
- 例: micro‑batch 推論で 3 ms 程度のカーネルを高頻度で呼ぶ場合、複数リクエストを束ねずとも GPU を飽和できる。
-
マルチモデル同時推論
- BERT + ResNet を同じ GPU でサービス。一方が Tensor Core を待つ間に他方が演算可能。
-
分散学習の parameter server プロセス
- 通常は CPU 側で実装するが、GPU での高速勾配集約を複数ワーカーで共有。
-
CI/CD や実験自動化パイプライン
- 短時間ジョブを高頻度で回し、GPU 利用率を均す。
-
GPU 枯渇環境での運用
- 研究所やスタートアップで高価なデータセンター GPU を持たず、ワークステーション GPU を最大活用。
※ 巨大モデルの単一バッチ学習 や Tensor 메모リを大量確保するワークロード には不向き。
■ MIGとの比較(表)
項目 | MPS | MIG |
---|---|---|
登場時期 | Kepler世代 (2013〜) | Ampere世代 (2020〜) |
リソース分離 | SM共有・メモリ共有(論理分離なし) | SM・メモリ・L2 Cache を HW レベルで完全分割 |
ユーザー分離 | 同一ユーザーのみ | 多ユーザー安全(論理 GPU として OS から切替可能) |
メモリ制限 | なし(早い者勝ち、cgroups 等で補完) | インスタンスごとに固定容量(例: 10 GB/20 GB) |
対象 GPU | RTX/GeForce/Quadro/Datacenter 全世代 | A100, H100, GH200, L40 などデータセンター GPU |
主な用途 | ワークステーションでの GPU 共有、推論ワーカー多重化 | クラウド GPU 分割、Kubernetes Pod への論理 GPU 割当 |
■ まとめ
- **MPS は「軽量 GPU マルチプレクサ」**─ メモリ共有前提なので、小規模・高頻度 ワークロードに向く。
- 設定は簡単: 環境変数 + デーモン起動のみ。Docker Compose でも同じ GPU を見せておけば動く。
-
メモリ管理は自己責任: keras/torch の
set_per_process_memory_fraction()
などアプリ側で制御しよう。 - MIG との使い分け: A100/H100 を持つなら MIG で“ハード分割”、それ以外は MPS で“ソフト共有”。
最後に、GPU リソース最適化は ベンチマークと監視が鍵。nvidia‑smi と exporter を常時走らせ、SM・メモリ飽和度を可視化しながら最適値を見つけよう。