Créer et gérer des types d’instances pour une utilisation efficace des ressources de calcul

Les types d’instances sont un concept d’Azure Machine Learning qui permet de cibler certains types de nœuds de calcul pour les charges de travail d’apprentissage et d’inférence. Par exemple, dans une machine virtuelle Azure, un type d’instance est STANDARD_D2_V3. Cet article vous apprend à créer et à gérer des types d’instance pour vos besoins de calcul.

Dans les clusters Kubernetes, les types d’instances sont représentés dans une définition de ressource personnalisée (CRD) qui est installée avec l’extension Azure Machine Learning. Deux éléments dans l’extension Azure Machine Learning représentent les types d’instances :

  • Utilisez nodeSelector pour vous permettre de spécifier le nœud sur lequel un pod doit s’exécuter. Le nœud doit avoir une étiquette correspondante.
  • Dans la section ressources, vous pouvez définir les ressources de calcul (processeur, mémoire et GPU NVIDIA) du pod.

Si vous spécifiez un champ nodeSelector lors du déploiement de l’extension Azure Machine Learning, le champ nodeSelector sera appliqué à tous les types d’instance. Cela signifie que :

  • Pour chaque type d’instance que vous créez, le champ nodeSelector spécifié doit être un sous-ensemble du champ nodeSelector spécifié par l’extension.
  • Si vous utilisez un type d’instance avec nodeSelector, la charge de travail s’exécute sur n’importe quel nœud correspondant à la fois au champ nodeSelector spécifié par l’extension et au champ nodeSelector spécifié par le type d’instance.
  • Si vous utilisez un type d’instance sans un champ nodeSelector, la charge de travail s’exécute sur n’importe quel nœud correspondant au champ nodeSelector spécifié par l’extension.

Créer un type d’instance par défaut

Par défaut, un type d’instance defaultinstancetype est créé lorsque vous attachez un cluster Kubernetes à un espace de travail Azure Machine Learning. Voici la définition :

resources:
  requests:
    cpu: "100m"
    memory: "2Gi"
  limits:
    cpu: "2"
    memory: "2Gi"
    nvidia.com/gpu: null

Si vous n’appliquez pas de champ nodeSelector, le pod peut être planifié sur n’importe quel nœud. Des ressources par défaut sont affectées aux pods de la charge de travail avec 0,1 cœur de processeur, 2 Go de mémoire et 0 GPU pour la requête. Les ressources utilisées par les pods de la charge de travail sont limitées à 2 cœurs de processeur et à 8 Go de mémoire.

Le type d’instance par défaut utilise peu de ressources. Pour garantir que toutes les charges de travail de Machine Learning s’exécutent avec les ressources appropriées (par exemple, une ressource GPU), nous vous recommandons vivement de créer des types d’instance personnalisées.

Gardez à l’esprit les points suivants concernant le type d’instance par défaut :

  • defaultinstancetype n’apparaît pas en tant que ressource personnalisée InstanceType dans le cluster lors de l’exécution de la commande kubectl get instancetype, mais apparaît dans tous les clients (IU, Azure CLI, SDK).
  • defaultinstancetype peut être remplacé par la définition d’un type d’instance personnalisé portant le même nom.

Créer un type d’instance personnalisée

Pour créer un nouveau type d’instance, créez une ressource personnalisée pour le type d’instance CRD. Par exemple :

kubectl apply -f my_instance_type.yaml

Voici le contenu de my_instance_type_list.yaml :

apiVersion: amlarc.azureml.com/v1alpha1
kind: InstanceType
metadata:
  name: myinstancetypename
spec:
  nodeSelector:
    mylabel: mylabelvalue
  resources:
    limits:
      cpu: "1"
      nvidia.com/gpu: 1
      memory: "2Gi"
    requests:
      cpu: "700m"
      memory: "1500Mi"

Le code précédent crée un type d’instance avec le comportement étiqueté :

  • Les pods sont planifiés uniquement sur les nœuds avec l’étiquette mylabel: mylabelvalue.
  • Les demandes de ressources de 700m pour le processeur et de 1500Mi pour la mémoire sont affectées aux pods.
  • Des limites de ressources de 1 pour le processeur, de 2Gi pour la mémoire et de 1 pour GPU NVIDIA.

La création de types d’instance personnalisés doit répondre aux paramètres et règles de définition suivants, sinon elle échoue :

Paramètre Obligatoire ou facultatif Description
name Obligatoire Valeurs de chaîne, qui doivent être uniques dans un cluster.
CPU request Requis Valeurs de chaîne, qui ne peuvent pas être zéro ou vides.
Vous pouvez spécifier le processeur en millicœurs ; par exemple, 100m. Vous pouvez également le spécifier sous forme de nombres complets. Par exemple, "1" équivaut à 1000m.
Memory request Requis Valeurs de chaîne, qui ne peuvent pas être zéro ou vides.
Vous pouvez indiquer la mémoire sous forme d’un nombre entier + suffixe, par exemple 1024Mi pour 1 024 mébioctets (Mio).
CPU limit Requis Valeurs de chaîne, qui ne peuvent pas être zéro ou vides.
Vous pouvez spécifier le processeur en millicœurs ; par exemple, 100m. Vous pouvez également le spécifier sous forme de nombres complets. Par exemple, "1" équivaut à 1000m.
Memory limit Requis Valeurs de chaîne, qui ne peuvent pas être zéro ou vides.
Vous pouvez indiquer la mémoire sous forme d’un nombre entier + suffixe, par exemple 1024Mi pour 1024 Mio.
GPU Facultatif Valeurs entières, qui ne peuvent être spécifiées que dans la section limits.
Pour plus d’informations, consultez la documentation Kubernetes.
nodeSelector Facultatif Mappage des clés de chaîne et des valeurs.

Il est également possible de créer plusieurs types d’instances à la fois :

kubectl apply -f my_instance_type_list.yaml

Voici le contenu de my_instance_type_list.yaml :

apiVersion: amlarc.azureml.com/v1alpha1
kind: InstanceTypeList
items:
  - metadata:
      name: cpusmall
    spec:
      resources:
        requests:
          cpu: "100m"
          memory: "100Mi"
        limits:
          cpu: "1"
          nvidia.com/gpu: 0
          memory: "1Gi"

  - metadata:
      name: defaultinstancetype
    spec:
      resources:
        requests:
          cpu: "1"
          memory: "1Gi" 
        limits:
          cpu: "1"
          nvidia.com/gpu: 0
          memory: "1Gi"

L’exemple précédent crée deux types d’instances : cpusmall et defaultinstancetype. Cette définition defaultinstancetype remplace la définition defaultinstancetype créée lorsque vous avez attaché le cluster Kubernetes à l’espace de travail Azure Machine Learning.

Si vous soumettez une charge de travail de formation ou d’inférence sans type d’instance, elle utilise defaultinstancetype. Pour spécifier un type d’instance par défaut pour un cluster Kubernetes, créez un type d’instance avec le nom defaultinstancetype. C’est automatiquement reconnu comme valeur par défaut.

Sélectionner un type d’instance pour envoyer un travail de formation

Pour sélectionner un type d’instance pour un travail de formation à l’aide de l’interface Azure CLI (v2), spécifiez son nom dans le cadre de la section de propriétés resources dans le YAML du travail. Par exemple :

command: python -c "print('Hello world!')"
environment:
  image: library/python:latest
compute: azureml:<Kubernetes-compute_target_name>
resources:
  instance_type: <instance type name>

Dans l’exemple précédent, remplacez par <Kubernetes-compute_target_name> le nom de votre cible de calcul Kubernetes. Remplacez <instance type name> par le nom du type d’instance que vous souhaitez sélectionner. Si vous ne spécifiez pas une propriété instance_type, le système utilise defaultinstancetype pour envoyer le travail.

Sélectionner le type d’instance pour déployer un modèle

Pour sélectionner un type d’instance pour un modèle de déploiement à l’aide de l’interface Azure CLI (v2), spécifiez son nom pour la propriété instance_type dans le YAML de déploiement. Par exemple :

name: blue
app_insights_enabled: true
endpoint_name: <endpoint name>
model: 
  path: ./model/sklearn_mnist_model.pkl
code_configuration:
  code: ./script/
  scoring_script: score.py
instance_type: <instance type name>
environment: 
  conda_file: file:./model/conda.yml
  image: mcr.microsoft.com/azureml/openmpi3.1.2-ubuntu18.04:latest

Dans l’exemple précédent, remplacez <instance type name> par le nom du type d’instance que vous souhaitez sélectionner. Si vous ne spécifiez pas une propriété instance_type, le système utilise defaultinstancetype pour déployer le modèle.

Important

Pour le modèle de déploiement MLflow, la demande de ressource nécessite au moins 2 cœurs de processeur et 4 Go de mémoire. Si ce n'est pas le cas, le déploiement échouera.

Validation de la section de ressource

Vous pouvez utiliser la section resources pour définir la demande de ressources et limiter vos modèles de déploiement. Par exemple :

name: blue
app_insights_enabled: true
endpoint_name: <endpoint name>
model: 
  path: ./model/sklearn_mnist_model.pkl
code_configuration:
  code: ./script/
  scoring_script: score.py
environment: 
  conda_file: file:./model/conda.yml
  image: mcr.microsoft.com/azureml/openmpi3.1.2-ubuntu18.04:latest
resources:
  requests:
    cpu: "0.1"
    memory: "0.2Gi"
  limits:
    cpu: "0.2"
    #nvidia.com/gpu: 0
    memory: "0.5Gi"
instance_type: <instance type name>

Si vous utilisez la section resources, une définition de ressource valide doit répondre aux règles suivantes. Une définition de ressource non valide entraîne l’échec du déploiement de modèle.

Paramètre Obligatoire ou facultatif Description
requests:
cpu:
Obligatoire Valeurs de chaîne, qui ne peuvent pas être zéro ou vides.
Vous pouvez spécifier le processeur en millicœurs ; par exemple, 100m. Vous pouvez également le spécifier sous forme de nombres complets. Par exemple, "1" équivaut à 1000m.
requests:
memory:
Requis Valeurs de chaîne, qui ne peuvent pas être zéro ou vides.
Vous pouvez indiquer la mémoire sous forme d’un nombre entier + suffixe, par exemple 1024Mi pour 1024 Mio.
La mémoire ne peut pas être inférieure à 1 Mo.
limits:
cpu:
Facultatif
(obligatoire uniquement lorsque vous avez besoin de GPU)
Valeurs de chaîne, qui ne peuvent pas être zéro ou vides.
Vous pouvez spécifier le processeur en millicœurs ; par exemple, 100m. Vous pouvez également le spécifier sous forme de nombres complets. Par exemple, "1" équivaut à 1000m.
limits:
memory:
Facultatif
(obligatoire uniquement lorsque vous avez besoin de GPU)
Valeurs de chaîne, qui ne peuvent pas être zéro ou vides.
Vous pouvez indiquer la mémoire sous forme d’un nombre entier + suffixe, par exemple 1024Mi pour 1 024 Mio.
limits:
nvidia.com/gpu:
Facultatif
(obligatoire uniquement lorsque vous avez besoin de GPU)
Valeurs entières, qui ne peuvent être vides et ne peuvent être spécifiées que dans la section limits.
Pour plus d’informations, consultez la documentation Kubernetes.
Si vous n’avez besoin que du processeur, vous pouvez omettre toute la section limits.

Le type d’instance est requis pour le modèle de déploiement. Si vous avez défini la sectionresources et qu’elle sera validée par rapport au type d’instance, les règles sont les suivantes :

  • Avec une définition de la section resource valide, les limites des ressources doivent être inférieures aux limites de type d’instance. Dans le cas contraire, le déploiement échouera.
  • Si vous ne définissez pas un type d’instance, le système utilise defaultinstancetype pour la validation avec la section resources.
  • Si vous ne définissez pas la section resources, le système utilise le type d’instance pour créer le déploiement.

Étapes suivantes