Exécutez plusieurs services d'inférence sur un seul GPU en découpant sa mémoire grâce à la planification partagée des GPU.
Fonctionnement
Le module complémentaire de planification partagée des GPU découpe la mémoire du GPU entre les pods. Chaque service spécifie ses besoins en mémoire à l'aide de l'indicateur --gpumemory. Le planificateur regroupe les pods sur le même nœud GPU jusqu'à ce que la mémoire totale demandée atteigne la capacité physique du nœud.
Privilégiez la planification partagée des GPU lorsque la maximisation de l'utilisation des GPU est plus importante que l'isolation des pannes. Pour une isolation stricte, utilisez des nœuds GPU dédiés.
Limitations
La mémoire GPU totale demandée par tous les pods sur un nœud ne doit pas dépasser la mémoire GPU physique du nœud.
Les nœuds accélérés par GPU utilisent CUDA 11 par défaut. Ce guide requiert CUDA 12.0 ou version ultérieure.
ack-kserve doit être en mode Raw Deployment.
Prérequis
Assurez-vous de disposer des éléments suivants :
Un cluster ACK managé ou dédié avec des nœuds accélérés par GPU, exécutant Kubernetes 1.22 ou version ultérieure. Consultez la rubrique Ajouter des nœuds accélérés par GPU à un cluster ou Créer un cluster ACK dédié avec des nœuds accélérés par GPU.
CUDA 12.0 ou version ultérieure sur les nœuds GPU. La version par défaut est CUDA 11 ; ajoutez le tag
ack.aliyun.com/nvidia-driver-version:525.105.17au pool de nœuds pour CUDA 12. Consultez la rubrique Personnaliser la version du pilote NVIDIA GPU sur les nœuds.Le composant de planification partagée des GPU installé sur le cluster
Le client Arena version 0.9.15 ou ultérieure. Consultez la rubrique Configurer le client Arena.
cert-manager et ack-kserve installés, avec ack-kserve en mode Raw Deployment
Étape 1 : Préparer les données du modèle
Stockez le modèle dans un compartiment OSS ou un système de fichiers NAS. Ce guide utilise OSS. Consultez les rubriques Utiliser un volume provisionné statiquement ossfs 1.0 ou Monter un volume NAS provisionné statiquement.
-
Téléchargez le modèle Qwen1.5-0.5B-Chat.
git lfs install GIT_LFS_SKIP_SMUDGE=1 git clone https://www.modelscope.cn/Qwen/Qwen1.5-0.5B-Chat.git cd Qwen1.5-0.5B-Chat git lfs pull -
Téléversez les fichiers du modèle dans votre compartiment OSS.
Consultez la rubrique Installer ossutil .
ossutil mkdir oss://<your-bucket-name>/models/Qwen1.5-0.5B-Chat ossutil cp -r ./Qwen1.5-0.5B-Chat oss://<your-bucket-name>/models/Qwen1.5-0.5B-Chat -
Créez un volume persistant (PV) avec la configuration suivante.
Élément de configuration
Valeur
Persistent volume type
OSS
Name
llm-model
Certificate Access
ID AccessKey et secret AccessKey pour le compartiment OSS
Bucket ID
Le compartiment OSS créé à l'étape précédente
OSS path
/Qwen1.5-0.5B-Chat
-
Créez une revendication de volume persistant (PVC) liée au PV.
Élément de configuration
Valeur
Persistent volume claim type
OSS
Name
llm-model
Allocation mode
Sélectionnez Existing persistent volume
Existing persistent volume
Cliquez sur Select Existing persistent volume et sélectionnez le PV créé à l'étape précédente
Étape 2 : Déployer les services d'inférence
Déployez deux services d'inférence Qwen, chacun demandant 6 Go de mémoire GPU. Seule la valeur de --name diffère entre les commandes.
Démarrez le premier service :
arena serve kserve \
--name=qwen1 \
--image=kube-ai-registry.cn-shanghai.cr.aliyuncs.com/kube-ai/vllm:0.4.1 \
--gpumemory=6 \
--cpu=3 \
--memory=8Gi \
--data="llm-model:/mnt/models/Qwen1.5-0.5B-Chat" \
"python3 -m vllm.entrypoints.openai.api_server --port 8080 --trust-remote-code --served-model-name qwen --model /mnt/models/Qwen1.5-0.5B-Chat --dtype=half --max-model-len=4096"
Démarrez le deuxième service avec --name=qwen2.
Paramètres clés :
|
Paramètre |
Type |
Obligatoire |
Description |
|
|
String |
Oui |
Nom du service. Doit être globalement unique. |
|
|
String |
Oui |
Image du conteneur. |
|
|
Integer (GB) |
Non |
Allocation de mémoire GPU en Go, par exemple |
|
|
Integer |
Non |
Nombre de vCPU. |
|
|
String |
Non |
Allocation de RAM, par exemple |
|
|
String |
Non |
Montage PVC vers conteneur au format |
Étape 3 : Vérifier les services d'inférence
-
Vérifiez que les deux pods s'exécutent sur le même nœud GPU.
kubectl get pod -owide | grep qwenRésultat attendu :
qwen1-predictor-856568bdcf-5pfdq 1/1 Running 0 7m10s 10.130.XX.XX cn-beijing.172.16.XX.XX <none> <none> qwen2-predictor-6b477b587d-dpdnj 1/1 Running 0 4m3s 10.130.XX.XX cn-beijing.172.16.XX.XX <none> <none>Les deux pods s'exécutent sur le même nœud (
cn-beijing.172.16.XX.XX), ce qui confirme que le partage de GPU est actif. -
Vérifiez la mémoire GPU par pod (une commande par service) :
kubectl exec -it qwen1-predictor-856568bdcf-5pfdq -- nvidia-smi # First service kubectl exec -it qwen2-predictor-6b477b587d-dpdnj -- nvidia-smi # Second serviceRésultat attendu pour chaque pod : Mémoire GPU allouée au premier service d'inférence
Fri Jun 28 06:20:43 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 V100-SXM2-16GB On | 00000000:00:07.0 Off | 0 | | N/A 39C P0 53W / 300W | 5382MiB / 6144MiB | 0% Default | | | | N/A | +-----------------------------------------+----------------------+----------------------+ +---------------------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=======================================================================================| +---------------------------------------------------------------------------------------+Mémoire GPU allouée au deuxième service d'inférence
Fri Jun 28 06:40:17 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 V100-SXM2-16GB On | 00000000:00:07.0 Off | 0 | | N/A 39C P0 53W / 300W | 5382MiB / 6144MiB | 0% Default | | | | N/A | +-----------------------------------------+----------------------+----------------------+ +---------------------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=======================================================================================| +---------------------------------------------------------------------------------------+Chaque pod voit une limite de 6 Go (6 144 MiB), ce qui confirme que le partage de la mémoire GPU fonctionne comme configuré.
-
Envoyez une requête de test via la passerelle NGINX Ingress.
curl -H "Host: $(kubectl get inferenceservice qwen1 -o jsonpath='{.status.url}' | cut -d "/" -f 3)" \ -H "Content-Type: application/json" \ http://$(kubectl -n kube-system get svc nginx-ingress-lb -ojsonpath='{.status.loadBalancer.ingress[0].ip}'):80/v1/chat/completions \ -d '{ "model": "qwen", "messages": [{"role": "user", "content": "This is a test."}], "max_tokens": 10, "temperature": 0.7, "top_p": 0.9, "seed": 10 }'Résultat attendu :
{"id":"cmpl-bbca59499ab244e1aabfe2c354bf6ad5","object":"chat.completion","created":1719303373,"model":"qwen","choices":[{"index":0,"message":{"role":"assistant","content":"OK. What do you want to test?"},"logprobs":null,"finish_reason":"length","stop_reason":null}],"usage":{"prompt_tokens":21,"total_tokens":31,"completion_tokens":10}}Une réponse confirme que le service d'inférence fonctionne correctement.
(Facultatif) Étape 4 : Nettoyer les ressources
Supprimez les ressources lorsqu'elles ne sont plus nécessaires.
Supprimez les services d'inférence :
arena serve delete qwen1
arena serve delete qwen2
Supprimez le PVC et le PV :
kubectl delete pvc llm-model
kubectl delete pv llm-model