使用 NVIDIA MPS 與多個工作負載共用 GPU

本頁面說明如何使用 CUDA 多程序服務 (MPS),讓多個工作負載在 Google Kubernetes Engine (GKE) 節點中共用單一 NVIDIA GPU 硬體加速器。

總覽

NVIDIA MPS 是一種 GPU 共用解決方案,可讓多個容器共用連接至節點的單一實體 NVIDIA GPU 硬體。

NVIDIA MPS 仰賴 NVIDIA 的 CUDA 多程序服務。NVIDIA MPS 是 CUDA API 的替代二進位相容實作,旨在以透明方式讓協作多程序 CUDA 應用程式在單一 GPU 裝置上同時執行。

您可以使用 NVIDIA MPS,指定實體 GPU 的共用容器數量上限。這個值會決定每個容器可獲得多少實體 GPU 功率,以以下特徵來說明:

如要進一步瞭解如何使用 NVIDIA MPS 排定 GPU,以及何時應使用 CUDA MPS,請參閱「About GPU sharing solutions in GKE」(關於 GKE 中的 GPU 共用解決方案)。

本指南適用對象

如果您符合下列任一條件,請按照本節的操作說明進行:

  • 平台管理員:建立及管理 GKE 叢集、規劃基礎架構和資源需求,以及監控叢集效能。
  • 應用程式開發人員:在 GKE 叢集上設計及部署工作負載。如需使用 GPU 要求 NVIDIA MPS 的操作說明,請參閱「部署使用 NVIDIA MPS 搭配 GPU 的工作負載」。

需求條件

  • GKE 版本:您可以在執行 GKE 1.27.7-gke.1088000 以上版本的 GKE Standard 叢集上,透過 NVIDIA MPS 啟用 GPU 共用功能。
  • GPU 類型:您可以為所有 NVIDIA GPU 類型啟用 NVIDIA MPS。不過,如果 G4 機型的 GPU 數量少於一個,就無法啟用 NVIDIA MPS。

事前準備

開始之前,請確認您已執行下列工作:

  • 啟用 Google Kubernetes Engine API。
  • 啟用 Google Kubernetes Engine API
  • 如要使用 Google Cloud CLI 執行這項工作,請安裝並初始化 gcloud CLI。如果您先前已安裝 gcloud CLI,請執行 gcloud components update 指令,取得最新版本。較舊的 gcloud CLI 版本可能不支援執行本文中的指令。

在 GKE 叢集啟用 NVIDIA MPS 和 GPU

平台管理員必須在 GKE Standard 叢集上,啟用 NVIDIA MPS 搭配 GPU。應用程式開發人員接著可以部署工作負載,透過 GPU 使用 NVIDIA MPS。如要在 GKE 上使用 GPU 啟用 NVIDIA MPS,請按照下列步驟操作:

  1. 在新的 GKE 叢集上啟用 NVIDIA MPS 和 GPU。
  2. 安裝 NVIDIA GPU 裝置驅動程式 (如有需要)。
  3. 驗證節點上可用的 GPU 資源。

在 GKE 叢集上啟用 NVIDIA MPS 和 GPU

建立 GKE Standard 叢集時,您可以啟用具備 GPU 的 NVIDIA MPS。叢集中的預設節點集區已啟用這項功能。在該叢集中手動建立新的節點集區時,仍須為 GPU 啟用 NVIDIA MPS。

使用 Google Cloud CLI 建立已啟用 NVIDIA MPS 的叢集:

gcloud container clusters create CLUSTER_NAME \
    --location=CONTROL_PLANE_LOCATION \
    --cluster-version=CLUSTER_VERSION \
    --machine-type=MACHINE_TYPE \
    --accelerator=type=GPU_TYPE,count=GPU_QUANTITY,gpu-sharing-strategy=mps,max-shared-clients-per-gpu=CLIENTS_PER_GPU,gpu-driver-version=DRIVER_VERSION

更改下列內容:

  • CLUSTER_NAME:新叢集的名稱。
  • CONTROL_PLANE_LOCATION:叢集控制層的 Compute Engine 位置。提供區域叢集的區域,或可用區叢集的可用區。所用 GPU 類型必須在所選區域可用。
  • CLUSTER_VERSION:叢集控制層和節點的 GKE 版本。使用 GKE 1.27.7-gke.1088000 以上版本。或者,您也可以使用 --release-channel=RELEASE_CHANNEL 旗標,指定具有該 GKE 版本的發布管道。
  • MACHINE_TYPE:節點的 Compute Engine 機型。相容的機器系列因 GPU 類型而異。舉例來說,如要使用 A100 GPU,請使用 A2 機器類型。如要依 GPU 找出更多相容的機器系列,請參閱「GPU 機型」。
  • GPU_TYPE: :GPU 類型,必須是 NVIDIA GPU 平台,例如 nvidia-tesla-v100。
  • GPU_QUANTITY:要附加至預設節點集區中每個節點的實體 GPU 數量。
  • CLIENTS_PER_GPU:可共用每個實體 GPU 的容器數量上限。
  • DRIVER_VERSION:要安裝的 NVIDIA 驅動程式版本。可以是下列任一值:
    • default:安裝 GKE 版本的預設驅動程式版本。
    • latest:為 GKE 版本安裝最新可用驅動程式版本。僅適用於使用 Container-Optimized OS 的節點。
    • disabled:略過自動安裝驅動程式。建立節點集區後,您必須 手動安裝驅動程式。如果省略 gpu-driver-version,則會使用這個預設選項。

在新的節點集區中啟用 NVIDIA MPS 和 GPU

在 GKE 叢集中手動建立新的節點集區時,您可以啟用 NVIDIA MPS 和 GPU。使用 Google Cloud CLI 建立啟用 NVIDIA MPS 的節點集區:

gcloud container node-pools create NODEPOOL_NAME \
    --cluster=CLUSTER_NAME \
    --machine-type=MACHINE_TYPE \
    --location=CONTROL_PLANE_LOCATION \
    --accelerator=type=GPU_TYPE,count=GPU_QUANTITY,gpu-sharing-strategy=mps,max-shared-clients-per-gpu=CONTAINER_PER_GPU,gpu-driver-version=DRIVER_VERSION

更改下列內容:

  • NODEPOOL_NAME:新節點集區的名稱。
  • CLUSTER_NAME:叢集名稱,必須執行 GKE 1.27.7-gke.1088000 以上版本。
  • CONTROL_PLANE_LOCATION:叢集控制層的 Compute Engine 位置。提供區域叢集的區域,或可用區叢集的可用區。
  • MACHINE_TYPE:節點的 Compute Engine 機型。相容的機器系列因 GPU 類型而異。舉例來說,如果是 A100 GPU,請使用 A2 機型。如果是 L4 GPU,請使用 G2 機型。如要依 GPU 找出更多相容的機器系列,請參閱「GPU 機型」。
  • GPU_TYPE:GPU 類型,必須是 NVIDIA GPU 平台,例如 nvidia-tesla-v100。
  • GPU_QUANTITY:要附加至節點集區中各節點的實體 GPU 數量。
  • CONTAINER_PER_GPU:可共用每個實體 GPU 的容器數量上限。
  • DRIVER_VERSION:要安裝的 NVIDIA 驅動程式版本。可以是下列任一值:

    • default:安裝 GKE 版本的預設驅動程式版本。
    • latest:為 GKE 版本安裝最新可用驅動程式版本。僅適用於使用 Container-Optimized OS 的節點。
    • disabled::略過自動安裝驅動程式。建立節點集區後,您必須 手動安裝驅動程式。如果省略 gpu-driver-version,系統會預設使用這個選項。

安裝 NVIDIA GPU 裝置驅動程式

如果在建立叢集時選擇停用自動安裝驅動程式,或是使用 1.27.2-gke.1200 之前的 GKE 版本,則必須手動安裝相容的 NVIDIA 驅動程式,才能管理實體 GPU 的 NVIDIA MPS 分割。如要安裝驅動程式,請部署 GKE 安裝 DaemonSet,以便設定驅動程式。

如需操作說明,請參閱「安裝 NVIDIA GPU 裝置驅動程式」。

確認可用的 GPU 資源

您可以確認節點中的 GPU 數量是否與啟用 NVIDIA MPS 時指定的數量相符。您也可以確認 NVIDIA MPS 控制精靈是否正在執行。

確認節點可用的 GPU 資源

如要確認節點可用的 GPU 資源,請執行下列指令:

kubectl describe nodes NODE_NAME

將 NODE_NAME 替換為節點名稱。

輸出結果會與下列內容相似:

...
Capacity:
  ...
  nvidia.com/gpu:             3
Allocatable:
  ...
  nvidia.com/gpu:             3

在這項輸出內容中,節點上的 GPU 資源數量為 3,因為值如下:

  • max-shared-clients-per-gpu 中的值為 3。
  • 要附加至節點的實體 GPU count數量為 1。如果實體 GPU 的 count 為 2,輸出內容會顯示 6 個可分配的 GPU 資源,每個實體 GPU 各有三個。

確認 MPS 控制 Daemon 正在執行

GPU 裝置外掛程式會對 MPS 控制 Daemon 執行健康狀態檢查。MPS 控制項 Daemon 正常運作時,即可部署容器。

如要驗證 NVIDIA MPS 狀態,請執行下列指令:

kubectl logs -l k8s-app=nvidia-gpu-device-plugin -n kube-system \
      -c nvidia-gpu-device-plugin --tail=100 | grep MPS

輸出結果會與下列內容相似:

I1118 08:08:41.732875       1 nvidia_gpu.go:75] device-plugin started
...
I1110 18:57:54.224832       1 manager.go:285] MPS is healthy, active thread percentage = 100.0
...

輸出內容可能會顯示下列事件:

  • failed to start GPU device manager 錯誤會先於 MPS is healthy 錯誤顯示。這是暫時性錯誤。如果看到 MPS is healthy 訊息,表示控制項精靈正在執行。
  • active thread percentage = 100.0 訊息表示整個實體 GPU 資源都有完全活躍的執行緒。

部署使用 MPS 的工作負載

部署 GPU 工作負載的應用程式運算子,可以指示 GKE 共用同一實體 GPU 中的 MPS 共用單位。在下列資訊清單中,您要求一個實體 GPU 並設定 max-shared-clients-per-gpu=3。實體 GPU 取得三個 MPS 共用單位,並啟動 nvidia/samples:nbody 工作,其中三個 Pod (容器) 平行執行。

  1. 將資訊清單儲存為 gpu-mps.yaml:

      apiVersion: batch/v1
      kind: Job
      metadata:
        name: nbody-sample
      spec:
        # Specifies the desired number of successfully finished Pods.
        completions: 3
        # Specifies the maximum desired number of Pods that should run at any given time.
        parallelism: 3
        template:
          spec:
            # Allows the Pod to share the host's IPC namespace.
            # The following field is required for containers to communicate with the MPS control daemon.
            hostIPC: true
            # Selects a node with the 'mps' GPU sharing strategy.
            nodeSelector:
              cloud.google.com/gke-gpu-sharing-strategy: mps
            containers:
              - name: nbody-sample
                # A sample CUDA application from NVIDIA.
                image: nvidia/samples:nbody
                # The command to run in the container.
                command: ["/tmp/nbody"]
                # Arguments for the command. Runs the nbody simulation in benchmark mode.
                args: ["-benchmark", "-i=5000"]
                resources:
                  limits:
                    # Requests one MPS sharing unit from a physical GPU.
                    nvidia.com/gpu: 1
            restartPolicy: "Never"
        backoffLimit: 1
    

    在這個資訊清單中:

    • hostIPC: true 可讓 Pod 與 MPS 控制 Daemon 通訊。這是必要欄位。不過,請注意,hostIPC: true 設定允許容器存取主機資源,這會帶來安全風險。
    • 在基準模式下執行 5,000 次疊代。
  2. 套用資訊清單:

    kubectl apply -f gpu-mps.yaml
    
  3. 確認所有 Pod 都在執行中:

    kubectl get pods
    

    輸出結果會與下列內容相似:

    NAME                           READY   STATUS    RESTARTS   AGE
    nbody-sample-6948ff4484-54p6q   1/1     Running   0          2m6s
    nbody-sample-6948ff4484-5qs6n   1/1     Running   0          2m6s
    nbody-sample-6948ff4484-5zpdc   1/1     Running   0          2m5s
    
  4. 查看 Pod 的記錄,確認工作已完成:

    kubectl logs -l job-name=nbody-sample -f
    

    輸出結果會與下列內容相似:

    ...
    > Compute 8.9 CUDA device: [NVIDIA L4]
    18432 bodies, total time for 5000 iterations: 9907.976 ms
    = 171.447 billion interactions per second
    = 3428.941 single-precision GFLOP/s at 20 flops per interaction
    ...
    

    由於 GKE 會執行 5,000 次疊代,記錄可能需要幾分鐘才會顯示。

清除所用資源

執行下列指令,刪除工作和所有 Pod:

kubectl delete job --all

使用 NVIDIA MPS 限制固定的裝置記憶體和有效執行緒

根據預設,在 GKE 上搭配 NVIDIA MPS 使用 GPU 時,下列 CUDA 環境變數會插入 GPU 工作負載:

  • CUDA_MPS_ACTIVE_THREAD_PERCENTAGE:這個變數代表每個 MPS 共用單元可使用的可用執行緒百分比。根據預設,GPU 的每個 MPS 共用單元都會設為 100 / MaxSharedClientsPerGPU,以取得同等比例的 GPU 運算資源 (以串流多處理器 (Streaming Multiprocessor) 為準)。
  • CUDA_MPS_PINNED_DEVICE_MEM_LIMIT:這個變數會限制 GPU 的 MPS 共用單元可分配的 GPU 記憶體量。根據預設,GPU 的每個 MPS 共用單位都會設為 total mem / MaxSharedClientsPerGPU,以取得相等的 GPU 記憶體配量。

如要設定 GPU 工作負載的資源限制,請設定下列 NVIDIA MPS 環境變數:

  1. 在 GitHub 中查看並建構 cuda-mps 範例的映像檔。

  2. 將下列資訊清單儲存為 cuda-mem-and-sm-count.yaml:

    apiVersion: v1
    kind: Pod
    metadata:
      name: cuda-mem-and-sm-count
    spec:
      # Allows the Pod to share the host's IPC namespace.
      # The following field is required for containers to communicate with the MPS control daemon.
      hostIPC: true
      # Selects a node with the 'mps' GPU sharing strategy.
      nodeSelector:
        cloud.google.com/gke-gpu-sharing-strategy: mps
      containers:
        - name: cuda-mem-and-sm-count
          # The custom image built from the cuda-mps example.
          image: CUDA_MPS_IMAGE
          # Grants the container extended privileges on the host machine.
          securityContext:
            privileged: true
          resources:
            limits:
              # Requests one MPS sharing unit from a physical GPU.
              nvidia.com/gpu: 1
    

    將 CUDA_MPS_IMAGE 替換為您為 cuda-mps 範例建構的映像檔名稱。

    NVIDIA MPS 需要在 Pod 上設定 hostIPC:true。hostIPC:true 設定允許容器存取主機資源,這會帶來安全性風險。

  3. 套用資訊清單:

    kubectl apply -f cuda-mem-and-sm-count.yaml
    
  4. 檢查這個 Pod 的記錄:

    kubectl logs cuda-mem-and-sm-count
    

    在以下範例中,我們使用 NVIDIA Tesla L4 搭配 gpu-sharing-strategy=mps 和 max-shared-clients-per-gpu=3,輸出內容大致如下:

    For device 0:  Free memory: 7607 M, Total memory: 22491 M
    For device 0:  multiProcessorCount: 18
    

    在本例中,NVIDIA Tesla L4 GPU 的 SM 數量為 60,記憶體為 24 GB。每個 MPS 共用單元大約可取得 33% 的作用中執行緒和 8 GB 的記憶體。

  5. 更新資訊清單,要求 2 個 nvidia.com/gpu:

      resources:
            limits:
              nvidia.com/gpu: 2
    

    輸出結果會與下列內容相似:

    For device 0:  Free memory: 15230 M, Total memory: 22491 M
    For device 0:  multiProcessorCount: 38
    
  6. 更新資訊清單,覆寫 CUDA_MPS_ACTIVE_THREAD_PERCENTAGE 和 CUDA_MPS_PINNED_DEVICE_MEM_LIMIT 變數:

      env:
        - name: CUDA_MPS_ACTIVE_THREAD_PERCENTAGE
          value: "20"
        - name: CUDA_MPS_PINNED_DEVICE_MEM_LIMIT
          value: "0=8000M"
    

    輸出結果會與下列內容相似:

    For device 0:  Free memory: 7952 M, Total memory: 22491 M
    For device 0:  multiProcessorCount: 10
    

限制

  • 相較於 Volta 和後續 GPU 類型,NVIDIA P100 等 Volta 前 GPU (即將終止支援) 的 MPS 功能有限。Volta
  • GKE 透過 NVIDIA MPS,確保每個容器都能取得有限的固定裝置記憶體和活躍執行緒。不過,記憶體頻寬、編碼器或解碼器等其他資源,不會納入這些資源限制。因此,如果所有容器都要求相同的無限制資源,可能會對其他容器的效能造成負面影響。
  • NVIDIA MPS 有記憶體保護和錯誤控制限制。建議您評估這項限制,確保與工作負載相容。
  • NVIDIA MPS 要求您在 Pod 上設定 hostIPC:true。hostIPC:true 設定允許容器存取主機資源,這會帶來安全性風險。
  • 使用 NVIDIA MPS 時,GKE 可能會拒絕某些 GPU 要求,以免在分配容量時發生非預期行為。
  • 最多可有 48 個容器透過 NVIDIA MPS 共用一部實體 GPU (Volta 前的 GPU 僅支援 16 個)。規劃 NVIDIA MPS 設定時,請考量工作負載的資源需求和基礎實體 GPU 的容量,以最佳化效能和回應速度。
  • 如果 G4 機型的 GPU 數量少於一個,則無法啟用 NVIDIA MPS。

後續步驟