全部產品
Search
文件中心

Container Service for Kubernetes:使用MPS實現GPU共用調度和顯存隔離

更新時間:Nov 27, 2024

共用GPU調度支援通過NVIDIA MPS(Multi-Process Service)作為底層GPU隔離模組,實現多個Pod共用同一張GPU卡,並確保各Pod之間的顯存隔離。本文將為您介紹如何啟用NVIDIA MPS隔離功能,並將其與共用GPU調度組件整合使用。

背景資訊

基於MPI實現CPU核並行化,可以平衡CPU密集型任務之間的資源分派,確保多個計算任務能夠同時進行,從而加速整體的計算過程。但當使用CUDA核心加速MPI進程時,每個MPI進程所分配到的工作量可能無法充分利用GPU,導致雖然每個MPI進程運行速度有所提高,但整體GPU的使用效率很低。當單個應用程式發送給GPU的任務量不足,GPU存在閑置資源時,推薦您使用NVIDIA MPS(Multi-Process Service),一種用於在NVIDIA GPU上運行多個CUDA應用程式的技術,適合用於多使用者環境或需要同時運行多個小任務的情境,從而提升GPU利用率和應用程式的輸送量。

MPS允許不同的應用程式在同一個GPU裝置上並發執行,以提高叢集GPU資源的利用率。MPS通過Client-Server架構來實現了這種功能,確保了二進位相容性,即您無需對現有的CUDA應用程式進行重大改造。MPS的構成組件如下。

  • Control Daemon Process:負責啟動和停止MPS Server,並協調用戶端和MPS Server之間的串連,確保用戶端能夠順利接入到MPS服務中進行GPU資源的請求和使用。

  • Client Runtime:整合於CUDA驅動程式庫內部。開發人員無需對CUDA應用程式代碼進行重大改造即可使用MPS。當應用程式使用CUDA驅動進行GPU操作時,Client Runtime會自動處理與MPS Server的互動,從而使多個應用程式能夠高效、安全地共用GPU。

  • Server Process:接收來自不同用戶端的請求,通過高效的調度策略將請求運行在一個GPU裝置上,從而實現了用戶端之間的並發性。

注意事項

  • 在NVIDIA MPS架構下,MPS Client(您提交的使用MPS功能的GPU應用)需要跟MPS Control Daemon保持互動。一旦MPS Control Daemon重啟,這些MPS Client將錯誤退出。

  • 在本樣本中,MPS Control Daemon服務以容器化的方式運行,以DaemonSet的形式在每個GPU節點部署一個MPS Control Daemon Pod,對於MPS Control Daemon Pod說明如下。

    • MPS Control Daemon Pod不能隨意刪除或重啟。刪除MPS Control Daemon Pod將會導致節點的GPU應用不可用。您可以通過命令kubectl get po -l app.aliyun.com/name=mps-control-daemon -A查詢叢集中MPS Control Daemon Pod狀態。

    • 容器中運行MPS Control Daemon時,容器需要具有privilegedhostIPChostPID的許可權。這可能帶來一些潛在風險,請謹慎評估後再決定是否使用該方案。

    • MPS Control Daemon Pod使用priorityClassName: system-node-critical來保證其優先順序,以避免節點資源不足時MPS Control Daemon Pod會被終止,繼而導致業務程式無法使用。如果在部署MPS Control Daemon組件的過程中遇到節點資源不足的情況,MPS Control Daemon可能會搶佔其他優先順序較低的業務Pod,導致這些業務Pod被驅逐。請在部署組件前,確保節點CPU、記憶體等資源充足。

  • 針對納入K8s叢集管理的GPU節點,為業務應用申請和使用GPU資源時,請關注以下注意事項。

    • 請勿直接在節點上運行GPU應用程式。

    • 請勿通過dockerpodmannerdctl等工具命令建立容器並為容器申請GPU資源。例如,執行docker run --gpus alldocker run -e NVIDIA_VISIBLE_DEVICES=all並運行GPU程式。

    • 請勿在Pod YAML的env中直接添加環境變數NVIDIA_VISIBLE_DEVICES=allNVIDIA_VISIBLE_DEVICES=<GPU ID>等,通過容器的環境變數NVIDIA_VISIBLE_DEVICES直接為Pod申請GPU資源,並運行GPU程式。

    • 在Pod YAML中未設定環境變數NVIDIA_VISIBLE_DEVICES,製作Pod所使用的鏡像時,請勿將環境變數預設配置為NVIDIA_VISIBLE_DEVICES=all,並運行GPU程式。

    • 請勿在Pod的securityContext中配置privileged: true,並運行GPU程式。

  • 通過以上非標方式為業務應用申請的GPU資源,將存在如下安全隱患。

    • 通過以上方式為業務應用申請的GPU資源,並未在調度器的裝置資源賬本中統計,有可能造成節點GPU資源的分配情況與調度器裝置資源賬本中記錄的值不一致。調度器仍然會調度某些申請GPU資源的Pod到這個節點上,導致使用者業務因為在同一張GPU卡上出現資源爭搶(比如GPU顯存申請)而運行失敗的情況。

    • 非標操作可能引發其他未知問題,例如NVIDIA社區的已知報錯

前提條件

已建立ACK託管叢集Pro版,且版本為1.20及以上。具體操作請參見建立ACK託管叢集升級叢集

操作步驟

步驟一:安裝MPS Control Daemon組件

  1. 登入Container Service管理主控台,在左側導覽列選擇市場 > 應用市場

  2. 進入應用市場介面,在搜尋方塊輸入ack-mps-control,然後單擊搜尋到的組件,進入其安裝介面。

  3. ack-mps-control安裝介面,單擊一鍵部署,選擇需要部署組件的叢集,然後單擊下一步

  4. 建立頁面,選擇對應Chart版本,然後單擊確定完成安裝。

    重要

    卸載和升級MPS Control Daemon組件ack-mps-control都會影響節點上已經啟動並執行GPU應用,導致GPU應用錯誤退出。請在業務低峰期執行這些操作。

步驟二:安裝共用GPU組件

  1. 登入Container Service管理主控台,在左側導覽列選擇叢集

  2. 叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇應用 > 雲原生AI套件

  3. 雲原生AI套件頁面,單擊一鍵部署

  4. 在一鍵部署雲原生AI套件頁面,選中調度策略擴充(批量任務調度、GPU共用、GPU拓撲感知)

  5. 雲原生AI套件頁面最下方,單擊部署雲原生AI套件

    組件安裝成功後,在雲原生AI套件頁面的組件列表中能看到已安裝的共用GPU組件ack-ai-installer

步驟三:開啟GPU共用調度能力和顯存隔離能力

  1. 叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇節點管理 > 節點池

  2. 節點池頁面,單擊建立節點池

  3. 建立節點池頁面,設定建立節點池的配置項,然後單擊確認配置

    以下為重要配置項的說明,其餘配置項的配置方法,請參見建立節點池

    配置項

    說明

    期望節點數

    設定節點池初始節點數量。如無需建立節點,可以填寫為0。

    說明

    完成建立節點池後,您還可以在節點池中添加GPU節點。添加GPU節點時,您需要將執行個體規格架構設定為GPU雲端服務器。具體操作,請參見添加已有節點建立節點池

    節點標籤

    單擊節點標籤節點標籤,設定為ack.node.gpu.schedule,為mps。

    重要

步驟四:安裝共用GPU查詢工具

  1. 下載kubectl-inspect-cgpu。

    • 如果您使用的是Linux系統,您可以通過以下命令下載kubectl-inspect-cgpu。

      wget http://aliacs-k8s-cn-beijing.oss-cn-beijing.aliyuncs.com/gpushare/kubectl-inspect-cgpu-linux -O /usr/local/bin/kubectl-inspect-cgpu
    • 如果您使用的是macOS系統,您可以通過以下命令下載kubectl-inspect-cgpu。

      wget http://aliacs-k8s-cn-beijing.oss-cn-beijing.aliyuncs.com/gpushare/kubectl-inspect-cgpu-darwin -O /usr/local/bin/kubectl-inspect-cgpu
  2. 執行以下命令,為kubectl-inspect-cgpu添加執行許可權。

    chmod +x /usr/local/bin/kubectl-inspect-cgpu
  3. 執行以下命令,查看叢集GPU使用方式。

    kubectl inspect cgpu

    預期輸出:

    NAME                       IPADDRESS      GPU0(Allocated/Total)  GPU Memory(GiB)
    cn-shanghai.192.168.6.104  192.168.6.104  0/15                   0/15
    ----------------------------------------------------------------------
    Allocated/Total GPU Memory In Cluster:
    0/15 (0%)

步驟五:部署樣本應用

  1. 使用如下YAML建立一個樣本應用。

    apiVersion: batch/v1
    kind: Job
    metadata:
      name: mps-sample
    spec:
      parallelism: 1
      template:
        metadata:
          labels:
            app: mps-sample
        spec:
          hostIPC: true  # 需要設定的選項,否則Pod會啟動失敗。
          hostPID: true  # 不需要設定此選項,此處設定只是便於看到使用MPS的效果。
          containers:
          - name: mps-sample
            image: registry.cn-hangzhou.aliyuncs.com/ai-samples/gpushare-sample:tensorflow-1.5
            command:
            - python
            - tensorflow-sample-code/tfjob/docker/mnist/main.py
            - --max_steps=100000
            - --data_dir=tensorflow-sample-code/data
            resources:
              limits: 
                aliyun.com/gpu-mem: 7  # 為該Pod申請7GiB顯存。
            workingDir: /root
          restartPolicy: Never
    說明

    當節點開啟MPS能力後,在該節點上啟動並執行GPU應用Pod需要配置hostIPC: true,否則Pod會啟動失敗。

  2. 等待Pod建立並處於Running狀態,使用如下命令查看MPS是否使用。

    kubectl exec -ti mps-sample-xxxxx --  nvidia-smi

    預期輸出:

    Tue Nov 12 11:09:35 2024
    +---------------------------------------------------------------------------------------+
    | NVIDIA-SMI 535.161.07             Driver Version: 535.161.07   CUDA Version: 12.2     |
    |-----------------------------------------+----------------------+----------------------+
    | GPU  Name                 Persistence-M | Bus-Id        Disp.A | Volatile Uncorr. ECC |
    | Fan  Temp   Perf          Pwr:Usage/Cap |         Memory-Usage | GPU-Util  Compute M. |
    |                                         |                      |               MIG M. |
    |=========================================+======================+======================|
    |   0  Tesla xxxxxxxxxxxxxx           On  | 00000000:00:07.0 Off |                    0 |
    | N/A   37C    P0              56W / 300W |    345MiB / 32768MiB |      0%   E. Process |
    |                                         |                      |                  N/A |
    +-----------------------------------------+----------------------+----------------------+
    
    +---------------------------------------------------------------------------------------+
    | Processes:                                                                            |
    |  GPU   GI   CI        PID   Type   Process name                            GPU Memory |
    |        ID   ID                                                             Usage      |
    |=======================================================================================|
    |    0   N/A  N/A    197792      C   nvidia-cuda-mps-server                       30MiB |
    |    0   N/A  N/A    387820    M+C   python                                      312MiB |
    +---------------------------------------------------------------------------------------+

    可以看到,nvidia-smi命令輸出中,mps-server已經啟動,在宿主機上的進程號為197792,同時以MPS方式啟動了一個進程號為387820的Python程式,說明MPS是正常啟動並執行。