#0156（2025/05/31）NVIDIA MPS徹底解説

# 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。
* **環境変数**

  ```bash
  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 使用率
  ```
* **デーモン起動/停止**

  ```bash
  nvidia-cuda-mps-control -d          # 起動
  echo quit | nvidia-cuda-mps-control # 停止
  ```
* **Docker Compose 例 (同一 GPU 共有)**

  ```yaml
  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）

```text
──────────────────────────── ❶ 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レベル図）

```text
+-----------------------------------------------------------+
|                    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･メモリ飽和度を可視化しながら最適値を見つけよう。