使用cGPU服務可以隔離GPU資源,實現多個容器共用一張GPU卡。該服務作為阿里雲Container ServiceKubernetes版ACK(Container Service for Kubernetes)的組件對外提供服務,應用於高效能運算能力的情境,例如機器學習、深度學習、科學計算等,方便您更高效地利用GPU資源,以加速計算任務。本文介紹如何通過安裝並使用cGPU服務。
cGPU服務的隔離功能不支援以UVM的方式(即調用CUDA API cudaMallocManaged())申請顯存,請您使用其他方式申請顯存,例如調用cudaMalloc()等。更多資訊,請參見NVIDIA官方文檔。
前提條件
在進行本操作前,請確保GPU執行個體滿足以下要求:
GPU執行個體規格為gn7i、gn6i、gn6v、gn6e、gn5i、gn5、ebmgn7i、ebmgn6i、ebmgn7e、ebmgn6e。
GPU執行個體作業系統為CentOS、Ubuntu或Alibaba Cloud Linux。
GPU執行個體已安裝Tesla 418.87.01或更高版本的驅動。
GPU執行個體已安裝Docker 19.03.5或更高版本。
安裝cGPU服務
無論您是企業認證使用者還是個人實名認證使用者,推薦您通過ACK的Docker運行時環境安裝和使用cGPU服務。
安裝1.5.7版本的cGPU組件,可能會導致cGPU核心驅動出現死結現象(即並發執行的進程互相牽制),從而導致Linux Kernel Panic(即核心錯誤)問題,建議您安裝1.5.8及以上版本的cGPU,或將低版本cGPU逐步升級到1.5.8及以上版本,避免在新業務上出現核心錯誤問題。
建立叢集。
具體操作,請參見建立ACK託管叢集。
在叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇 。
在基礎能力地區,選中調度策略擴充(批量任務調度、GPU共用、GPU拓撲感知)。
單擊頁面底部的部署雲原生AI套件。
組件安裝成功後,在雲原生AI套件頁面的組件列表中能看到已安裝的共用GPU組件ack-ai-installer。
在雲原生AI套件頁面,單擊一鍵部署。
使用cGPU服務
本文以ecs.gn6i-c4g1.xlarge為例示範2個容器共用1張顯卡。
運行cGPU服務
執行以下命令,建立容器並設定容器內可見的顯存。
本樣本中,設定
ALIYUN_COM_GPU_MEM_CONTAINER
和ALIYUN_COM_GPU_MEM_DEV
環境變數指定顯卡的總顯存和容器內可見的顯存。例如建立2個容器:gpu_test1:分配6 GiB顯存。
sudo docker run -d -t --gpus all --shm-size=1g --ulimit memlock=-1 --ulimit stack=67108864 --name gpu_test1 -v /mnt:/mnt -e ALIYUN_COM_GPU_MEM_CONTAINER=6 -e ALIYUN_COM_GPU_MEM_DEV=15 nvcr.io/nvidia/tensorflow:19.10-py3
gpu_test2:分配8 GiB顯存。
sudo docker run -d -t --gpus all --shm-size=1g --ulimit memlock=-1 --ulimit stack=67108864 --name gpu_test2 -v /mnt:/mnt -e ALIYUN_COM_GPU_MEM_CONTAINER=8 -e ALIYUN_COM_GPU_MEM_DEV=15 nvcr.io/nvidia/tensorflow:19.10-py3
說明該命令以使用TensorFlow鏡像
nvcr.io/nvidia/tensorflow:19.10-py3
為例,請根據實際情況更換為您自己的容器鏡像。使用TensorFlow鏡像搭建TensorFlow深度學習架構的操作,請參見部署NGC環境構建深度學習開發環境。執行以下命令,查看容器的顯存等GPU資訊。
sudo docker exec -i gpu_test1 nvidia-smi
以gpu_test1為例,容器gpu_test1中可見的顯存為6043 MiB,如下圖所示:
通過procfs節點查看cGPU服務
cGPU服務運行時會在/proc/cgpu_km下產生並自動管理多個procfs節點,您可以通過procfs節點查看和配置cGPU服務相關的資訊。
執行以下命令,查看procfs節點資訊。
ls /proc/cgpu_km/
執行結果如下所示:
執行以下命令,查看GPU執行個體的顯卡目錄內容。
本樣本中,以顯卡0為例。
ls /proc/cgpu_km/0
執行結果如下所示:
執行以下命令,查看容器對應的目錄內容。
本樣本中,以012b2edccd7a容器為例。
ls /proc/cgpu_km/0/012b2edccd7a
執行結果如下所示:
(可選)執行以下命令,配置cGPU服務。
瞭解procfs節點的用途後,您可以在GPU執行個體中執行命令進行切換調度策略、修改權重等操作,樣本命令如下表所示。
命令
效果
echo 2 > /proc/cgpu_km/0/policy
將調度策略切換為權重搶佔調度。
cat /proc/cgpu_km/0/free_weight
查看顯卡上可用的權重。如果
free_weight=0
,新建立容器的權重值為0,該容器不能擷取GPU算力,不能用於運行需要GPU算力的應用。cat /proc/cgpu_km/0/$dockerid/weight
查看指定容器的權重。
echo 4 > /proc/cgpu_km/0/$dockerid/weight
修改容器擷取GPU算力的權重。
通過cgpu-smi工具查看cGPU容器
您可以通過cgpu-smi工具查看cGPU容器的相關資訊,包括容器ID、GPU利用率、算力限制、使用的顯存以及分配顯存的總量等資訊。
cgpu-smi是cGPU的監控樣本。部署k8s時,您可以參考或使用cgpu-smi的樣本做二次開發整合。
cgpu-smi的監控展示資訊如下所示:
升級或卸載cGPU服務
升級cGPU服務
升級cGPU服務支援冷升級和熱升級兩種方式。
冷升級
Docker未使用cGPU服務的情況下,採用冷升級方式升級cGPU服務,操作步驟如下:
執行以下命令,關閉所有運行中的容器。
sudo docker stop $(docker ps -a | awk '{ print $1}' | tail -n +2)
執行以下命令,升級cGPU服務至最新版本。
sudo sh upgrade.sh
熱升級
Docker使用cGPU服務的情況下,可以採用熱升級方式升級cGPU核心驅動,但是對於升級的版本有一定限制。 如需任何協助,請聯絡阿里雲售後技術團隊。
卸載cGPU服務
關於如何卸載節點上舊版本cGPU服務,具體操作,請參見通過命令升級節點cGPU版本。
cGPU服務使用樣本
cGPU服務算力調度樣本
cGPU服務載入cgpu_km的模組時,會按照容器最大數量(max_inst)為每張顯卡設定時間片(X ms),用於為容器分配GPU算力,本樣本中以Slice 1、Slice 2或Slice N表示。使用不同調度策略時的調度樣本如下所示。
平均調度(policy=0)
在建立容器時,為容器分配時間片。cGPU服務會從Slice 1時間片開始調度,提交任務到物理GPU,並執行一個時間片(X ms)的時間,然後切換到下一個時間片。每個容器獲得的算力相同,都為
1/max_inst
,如下所示。搶佔調度(policy=1)
在建立容器時,為容器分配時間片。cGPU服務會從Slice 1開始調度,但如果沒有使用某個容器,或者容器內沒有進程開啟GPU裝置,則跳過調度,切換到下一個時間片。
樣本如下:
只建立一個容器Docker 1,獲得Slice 1時間片,在Docker 1中運行2個TensorFlow進程,此時Docker 1最大獲得整個物理GPU的算力。
再建立一個容器Docker 2,獲得Slice 2時間片。如果Docker 2內沒有進程開啟GPU裝置,調度時會跳過Docker 2的時間片Slice 2。
當Docker 2有進程開啟GPU裝置時,Slice 1和Slice 2都加入調度,Docker 1和Docker 2最大分別獲得1/2物理GPU的算力,如下所示。
權重搶佔調度(policy=2)
如果在建立容器時設定ALIYUN_COM_GPU_SCHD_WEIGHT大於1,則自動使用權重搶佔調度。cGPU服務按照容器數量(max_inst)將物理GPU算力劃分成max_inst份,但如果ALIYUN_COM_GPU_SCHD_WEIGHT大於1,cGPU服務會將多個時間片組合成一個更大的時間片分配給容器。
設定樣本如下:
Docker 1:ALIYUN_COM_GPU_SCHD_WEIGHT=m
Docker 2:ALIYUN_COM_GPU_SCHD_WEIGHT=n
調度效果如下:
如果只有Docker 1運行, Docker 1搶佔整個物理GPU的算力。
如果Docker 1和Docker 2同時運行,Docker 1和Docker 2獲得的理論算力比例是m:n。和搶佔調度不同的是,即使Docker 2中沒有GPU進程也會佔用n個時間片的時間。
說明m:n設定為2:1和8:4時的運行表現存在差別。在1秒內切換時間片的次數,前者是後者的4倍。
權重搶佔調度限制了容器使用GPU算力的理論最大值。但對算力很強的顯卡(例如NVIDIA V100顯卡),如果顯存使用較少,在一個時間片內即可完成計算任務。此時如果m:n值設定為8:4,則剩餘時間片內GPU算力會閑置,限制基本失效。
固定算力調度(policy=3)
您可以通過指定ALIYUN_COM_GPU_SCHD_WEIGHT和max_inst的佔比,固定算力的百分比。
算力弱調度(policy=4)
在建立容器時,為容器分配時間片,隔離性弱於搶佔調度。更多資訊,請參見搶佔調度(policy=1)。
原生調度(policy=5)
只用來做顯存的隔離。原生調度表示NVIDIA GPU驅動本身的調度方式。
算力調度策略支援阿里雲所有的異構GPU執行個體,以及GPU執行個體所配備的NVIDIA顯卡,其型號包含Tesla P4、Tesla P100、Tesla T4、Tesla V100、Tesla A10。以下測試項使用2個容器共用一台單卡A10的GPU執行個體,並將2個容器的算力比設定為1:2,將顯存均分,每個容器的顯存為12 G。
以下效能測試結果資料為實驗室資料,僅供參考。
測試項1: 在基於TensorFlow架構訓練的ResNet50模型、精度為FP16的情境下,測試不同batch_size下的效能資料比較。結果如下所示:
架構
模型
batch_size
精度
images/sec(容器1)
images/sec(容器2)
TensorFlow
ResNet50
16
FP16
151
307
TensorFlow
ResNet50
32
FP16
204
418
TensorFlow
ResNet50
64
FP16
247
503
TensorFlow
ResNet50
128
FP16
257
516
測試項2:在基於TensorRT架構訓練的ResNet50模型、精度為FP16的情境下,測試不同batch_size下的效能資料比較。結果如下所示:
架構
模型
batch_size
精度
images/sec(容器1)
images/sec(容器2)
TensorRT
ResNet50
1
FP16
568.05
1132.08
TensorRT
ResNet50
2
FP16
940.36
1884.12
TensorRT
ResNet50
4
FP16
1304.03
2571.91
TensorRT
ResNet50
8
FP16
1586.87
3055.66
TensorRT
ResNet50
16
FP16
1783.91
3381.72
TensorRT
ResNet50
32
FP16
1989.28
3695.88
TensorRT
ResNet50
64
FP16
2105.81
3889.35
TensorRT
ResNet50
128
FP16
2205.25
3901.94
cGPU服務多卡劃分樣本
本樣本以設定4卡為例,設定0卡為3 G、1卡為4 G、2卡為5 G、3卡為6 G。多卡劃分範例程式碼如下所示:
docker run -d -t --runtime=nvidia --name gpu_test0123 --shm-size=1g --ulimit memlock=-1 --ulimit stack=67108864 -v /mnt:/mnt -e ALIYUN_COM_GPU_MEM_CONTAINER=3,4,5,6 -e ALIYUN_COM_GPU_MEM_DEV=23 -e NVIDIA_VISIBLE_DEVICES=0,1,2,3 nvcr.io/nvidia/tensorflow:21.03-tf1-py3
docker exec -i gpu_test0123 nvidia-smi
執行結果顯示如下,您可以看到4卡顯存詳情。
多卡設定顯存參數(即ALIYUN_COM_GPU_MEM_CONTAINER
參數)說明如下所示:
參數取值 | 說明 |
ALIYUN_COM_GPU_MEM_CONTAINER=3 | 表示4卡的顯存都被設定為3 G。 |
ALIYUN_COM_GPU_MEM_CONTAINER=3,1 | 表示4卡的顯存依次被設定為3 G、1 G、1 G、1 G。 |
ALIYUN_COM_GPU_MEM_CONTAINER=3,4,5,6 | 表示4卡的顯存依次被設定為3 G、4 G、5 G、6 G。 |
ALIYUN_COM_GPU_MEM_CONTAINER未設定 | 表示禁用cGPU服務。 |
ALIYUN_COM_GPU_MEM_CONTAINER=0 | |
ALIYUN_COM_GPU_MEM_CONTAINER=1,0,0 |