本文介紹如何在ACK靈駿托管版集群中的靈駿節點上使用共享GPU調度,實現GPU的共享和隔離能力。
前提條件
已創建ACK靈駿托管版集群,并且集群帶有GPU的靈駿節點。具體操作,請參見創建帶有ACK靈駿托管版的集群。
ACK靈駿托管版集群默認會安裝共享GPU調度組件,您可以在ACK靈駿托管集群中通過給GPU節點打上共享GPU調度的標簽開啟節點共享GPU調度能力。相關信息,請參見GPU節點調度屬性標簽說明。
使用共享GPU調度
對于使用共享GPU調度,一般分為如下兩種場景:
僅共享不隔離:允許多個Pod共同運行在同一塊GPU上,并不處理(或交由上層應用處理)這塊GPU卡上多個Pod之間相互影響的問題,例如爭搶GPU顯存資源等情況。
既共享又隔離:允許多個Pod運行在同一塊GPU上,同時也處理這塊GPU卡上多個Pod相互影響的問題。
場景1:僅共享不隔離
在部分場景中,不需要GPU隔離模塊參與共享GPU調度。有些業務應用本身提供顯存限制能力,例如Java應用啟動時,可以通過選項指定該應用的最大內存使用量。這種情況下,使用GPU隔離模塊隔離業務顯存會有資源沖突等問題。因此,共享GPU調度支持某些節點不安裝GPU隔離模塊的選項。
步驟一:開啟節點GPU共享調度能力
查找
/etc/lingjun_metadata
文件是否存在。如果文件存在,然后執行命令
nvidia-smi
,如果輸出正常,表明該節點為預期開啟共享GPU調度能力的靈駿節點,可繼續執行下一步。如果文件不存在,表明預期開啟共享GPU調度能力的節點不是靈駿節點,因此此節點無法開啟GPU共享調度能力。如果需要開啟GPU共享調度能力,請創建靈駿節點。具體操作,請參見靈駿節點池概述。
執行如下命令,通過給節點設置標簽
ack.node.gpu.schedule
為節點開啟共享GPU調度能力。
kubectl label node <NODE_NAME> ack.node.gpu.schedule=share
步驟二:使用GPU共享資源
使用以下示例創建
tensorflow.yaml
文件。apiVersion: batch/v1 kind: Job metadata: name: tensorflow-mnist-share spec: parallelism: 1 template: metadata: labels: app: tensorflow-mnist-share spec: # 該YAML定義了一個使用tensorflow mnist樣例的Job。Job有1個Pod,該Pod申請4 GiB顯存。 containers: - name: tensorflow-mnist-share image: registry.cn-beijing.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: # Pod申請4 GiB顯存通過在Pod resources.limits定義aliyun.com/gpu-mem: 4實現。 limits: aliyun.com/gpu-mem: 4 # 總共申請4 GiB顯存。 workingDir: /root restartPolicy: Never
執行如下命令,提交任務。
kubectl apply -f tensorflow.yaml
步驟三:驗證僅共享不隔離能力
找到前一步創建Job的Pod,使用kubectl執行如下命令。
kubectl get pod | grep tensorflow
kubectl exec -ti tensorflow-mnist-share-xxxxx -- nvidia-smi
預期輸出:
Wed Jun 14 06:45:56 2023
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 515.105.01 Driver Version: 515.105.01 CUDA Version: 11.7 |
|-------------------------------+----------------------+----------------------+
| 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 V100-SXM2... On | 00000000:00:09.0 Off | 0 |
| N/A 35C P0 59W / 300W | 334MiB / 16384MiB | 0% Default |
| | | N/A |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=============================================================================|
+-----------------------------------------------------------------------------+
Pod內部能夠發現整塊GPU卡的總顯存為16384 MiB,而在有隔離模塊參與的場景下,該值與Pod申請值一致,說明配置生效。
本示例中使用的GPU卡型號為V100,Pod顯存申請值為4 GiB,實際數據以您的操作環境為準。
業務應用需要從兩個環境變量中讀取該業務能夠使用的顯存值。
ALIYUN_COM_GPU_MEM_CONTAINER=4 # 該Pod能夠使用的顯存值。
ALIYUN_COM_GPU_MEM_DEV=16 # 每塊GPU卡總共的顯存值。
如果需要的是該應用使用的顯存占GPU卡總顯存的百分比。可以使用上述兩個環境變量得出。
percetange = ALIYUN_COM_GPU_MEM_CONTAINER / ALIYUN_COM_GPU_MEM_DEV = 4 / 16 = 0.25
場景2:既共享又隔離
在多個Pod共享一塊GPU前提下,隔離是一個關鍵的需求。如何限制運行在同一個GPU上的多個容器能夠按照自己申請的資源使用量運行,避免因為其資源用量超標影響同一個GPU上的其他容器的正常工作,對此業界也做了很多探索。NVIDIA vGPU、MPS和vCUDA、eGPU等方案,都為更小顆粒度的使用GPU提供了可能,下面以eGPU隔離模塊為例進行說明。
步驟一:開啟節點GPU共享調度能力
查找
/etc/lingjun_metadata
文件是否存在。如果文件存在,然后執行命令
nvidia-smi
,如果輸出正常,表明該節點為預期開啟共享GPU調度能力的靈駿節點,可繼續執行下一步。如果文件不存在,表明預期開啟共享GPU調度能力的節點不是靈駿節點,因此此節點無法開啟GPU共享調度能力。如果需要開啟GPU共享調度能力,請創建靈駿節點。具體操作,請參見靈駿節點池概述。
執行如下命令,通過給節點設置標簽
ack.node.gpu.schedule
為節點開啟共享GPU調度能力。kubectl label node <NODE_NAME> ack.node.gpu.schedule=egpu_mem
如果標簽的Value為egpu_mem,表示只進行GPU顯存隔離。本文以該標簽為例。
如果標簽的Value設置為egpu_core_mem,表示進行GPU顯存和算力雙隔離。
您可以只申請GPU顯存資源,但是如果要申請GPU算力資源,則需要同時申請GPU顯存資源和GPU算力資源。
步驟二:使用GPU共享資源
等待節點將共享GPU的資源上報結束。
執行如下命令,查看Node資源信息。
kubectl get node <NODE_NAME> -oyaml
預期輸出為:
allocatable:
aliyun.com/gpu-count: "1"
aliyun.com/gpu-mem: "80"
...
nvidia.com/gpu: "0"
...
capacity:
aliyun.com/gpu-count: "1"
aliyun.com/gpu-mem: "80
...
nvidia.com/gpu: "0"
...
預期輸出表明,節點資源列表中已存在aliyun.com/gpu-mem
,總共1塊GPU卡,80G顯存。
如果Pod需要調度并使用整卡資源,則需要在目標Pod上增加標簽ack.gpushare.placement=require-whole-device
,然后指定需要使用的GPU顯存數量gpu-mem
,則該Pod會被默認調度到擁有該數量顯存的整塊GPU上。
步驟三:運行共享GPU示例
使用如下YAML提交Benchmark任務。
apiVersion: batch/v1 kind: Job metadata: name: benchmark-job spec: parallelism: 1 template: spec: containers: - name: benchmark-job image: registry.cn-beijing.aliyuncs.com/ai-samples/gpushare-sample:benchmark-tensorflow-2.2.3 command: - bash - run.sh - --num_batches=500000000 - --batch_size=8 resources: limits: aliyun.com/gpu-mem: 10 # 申請10G顯存。 workingDir: /root restartPolicy: Never hostNetwork: true tolerations: - operator: Exists
執行如下命令,提交任務。
kubectl apply -f benchmark.yaml
等待Pod運行起來后,請使用如下命令進入Pod。
kubectl exec -ti benchmark-job-xxxx bash
在容器中執行如下命令,查看GPU隔離情況。
vgpu-smi
預期輸出為:
+------------------------------------------------------------------------------+ | VGPU_SMI 460.91.03 DRIVER_VERSION: 460.91.03 CUDA Version: 11.2 | +-------------------------------------------+----------------------------------+ | GPU Name Bus-Id | Memory-Usage GPU-Util | |===========================================+==================================| | 0 xxxxxxxx 00000000:00:07.0 | 8307MiB / 10782MiB 100% / 100% | +-------------------------------------------+----------------------------------+
預期輸出表明,Pod容器被分配了10 GB的顯存。
常見問題
如何查看是否已安裝共享GPU組件?
執行如下命令,查看是否已安裝基于eGPU的共享GPU組件。
kubectl get ds -nkube-system | grep gpushare
預期輸出:
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
gpushare-egpu-device-plugin-ds 0 0 0 0 0 <none>
gpushare-egpucore-device-plugin-ds 0 0 0 0 0 <none>
預期輸出表明,共享GPU組件已安裝。