Creare e gestire i tipi di istanza per l'utilizzo efficiente delle risorse di calcolo

I tipi di istanza sono un concetto di Azure Machine Learning che consente il targeting di determinati tipi di nodi di calcolo per carichi di lavoro di training e inferenza. Ad esempio, in una macchina virtuale di Azure, un tipo di istanza è STANDARD_D2_V3. Questo articolo illustra come creare e gestire i tipi di istanza per i requisiti di calcolo.

Nei cluster Kubernetes i tipi di istanza sono rappresentati in una definizione di risorsa personalizzata (CRD) installata con l'estensione Azure Machine Learning. Due elementi nell'estensione Azure Machine Learning rappresentano i tipi di istanza:

  • Usare nodeSelector per specificare il nodo in cui deve essere eseguito un pod. Il nodo deve avere un'etichetta corrispondente.
  • Nella sezione risorse è possibile impostare le risorse di calcolo (CPU, memoria e GPU NVIDIA) per il pod.

Se si specifica un campo nodeSelector durante la distribuzione dell'estensione Aazure Machine Learning, il campo nodeSelector verrà applicato a tutti i tipi di istanza. Ciò significa che:

  • Per ogni tipo di istanza creato, il campo nodeSelector specificato deve essere un subset del campo nodeSelector specificato dall'estensione.
  • Se si usa un tipo di istanza con nodeSelector, il carico di lavoro verrà eseguito in qualsiasi nodo che corrisponda sia al campo nodeSelector specificato dall'estensione che al campo nodeSelector specificato dal tipo di istanza.
  • Se si usa un tipo di istanza senza un campo nodeSelector, il carico di lavoro verrà eseguito in qualsiasi nodo che corrisponda al campo nodeSelector specificato dall'estensione.

Creare un tipo di istanza predefinita

Per impostazione predefinita, quando si collega un cluster Kubernetes a un'area di lavoro di Azure Machine Learning viene creato un tipo di istanza denominato defaultinstancetype. La definizione è la seguente:

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

Se non si applica un campo nodeSelector, il pod può essere pianificato in qualsiasi nodo. Ai pod del carico di lavoro vengono assegnate risorse predefinite con 0,1 core CPU, 2 GB di memoria e 0 GPU per la richiesta. Le risorse usate dai pod del carico di lavoro si limitano a 2 core CPU e 8 GB di memoria.

Il tipo di istanza predefinito usa intenzionalmente poche risorse. Per assicurarsi che tutti i carichi di lavoro di Machine Learning vengano eseguiti con risorse appropriate (ad esempio, risorsa GPU), è consigliabile creare tipi di istanze personalizzate.

Per il tipo di istanza predefinito, tenere presente quanto segue:

  • defaultinstancetype non viene visualizzato come InstanceType risorsa personalizzata nel cluster quando si esegue il comando kubectl get instancetype, ma viene visualizzato in tutti i client (interfaccia utente, interfaccia della riga di comando di Azure, SDK).
  • defaultinstancetype può essere sottoposto a override con la definizione di un tipo di istanza personalizzata con lo stesso nome.

Creare un tipo di istanza personalizzata

Per creare un nuovo tipo di istanza, creare una nuova risorsa personalizzata per il tipo di istanza CRD. Ad esempio:

kubectl apply -f my_instance_type.yaml

Il contenuto di my_instance_type.yaml è il seguente:

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"

Il codice precedente crea un tipo di istanza con il comportamento etichettato:

  • I pod vengono pianificati solo nei nodi con l'etichetta mylabel: mylabelvalue.
  • Ai pod vengono assegnate richieste di risorse di 700m per la CPU e 1500Mi per la memoria.
  • Ai pod vengono assegnati limiti di risorse di 1 per la CPU, 2Gi per la memoria e 1 per GPU NVIDIA.

La creazione di tipi di istanze personalizzate deve soddisfare i parametri e le regole di definizione seguenti, altrimenti darà esito negativo:

Parametro Obbligatorio o facoltativo Descrizione
name Richiesto Valori di stringa, che devono essere univoci in un cluster.
CPU request Richiesto Valori di stringa, che non possono essere pari a zero o vuoti.
È possibile specificare la CPU in millicore; ad esempio 100m. È anche possibile specificarla come numeri interi. Ad esempio, "1" equivale a 1000m.
Memory request Richiesto Valori di stringa, che non possono essere pari a zero o vuoti.
È possibile specificare la memoria come numero intero + suffisso; ad esempio, 1024Mi per 1.024 mebibyte (MiB).
CPU limit Richiesto Valori di stringa, che non possono essere pari a zero o vuoti.
È possibile specificare la CPU in millicore; ad esempio 100m. È anche possibile specificarla come numeri interi. Ad esempio, "1" equivale a 1000m.
Memory limit Richiesto Valori di stringa, che non possono essere pari a zero o vuoti.
È possibile specificare la memoria come numero intero + suffisso; ad esempio per 1024Mi 1024 MiB.
GPU Facoltativo Valori interi, che è possibile specificare solo nella sezione limits.
Per altre informazioni, vedere la documentazione di Kubernetes.
nodeSelector Facoltativo Mappa delle chiavi e dei valori delle stringhe.

È anche possibile creare tipi di istanza multipli contemporaneamente:

kubectl apply -f my_instance_type_list.yaml

Il contenuto di my_instance_type_list.yaml è il seguente:

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"

Nell'esempio precedente vengono creati due tipi di istanza: cpusmall e defaultinstancetype. Questa definizione defaultinstancetype esegue l'override della definizione defaultinstancetype creata quando il cluster Kubernetes è stato collegato all'area di lavoro di Azure Machine Learning.

Se si invia un carico di lavoro di training o inferenza senza un tipo di istanza, viene usato defaultinstancetype. Per specificare un tipo di istanza predefinito per un cluster Kubernetes, creare un tipo di istanza con il nome defaultinstancetype. Viene automaticamente riconosciuto come predefinito.

Selezionare un tipo di istanza per inviare un processo di training

Per selezionare un tipo di istanza per un processo di training usando l'interfaccia della riga di comando di Azure (v2), specificarne il nome come parte della sezione delle proprietà resources nel processo YAML. Ad esempio:

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

Nell'esempio precedente sostituire <Kubernetes-compute_target_name> con il nome della destinazione di calcolo Kubernetes. Sostituire <instance type name> con il nome del tipo di istanza che si desidera selezionare. Se non si specifica una proprietà instance_type, il sistema usa defaultinstancetype per inviare il processo.

Selezionare un tipo di istanza per distribuire un modello

Per selezionare un tipo di istanza per una distribuzione di modelli usando l'interfaccia della riga di comando di Azure (v2), specificare il nome per la proprietà instance_type nella distribuzione YAML. Ad esempio:

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

Nell'esempio precedente, sostituire <instance type name> con il nome del tipo di istanza che si desidera selezionare. Se non si specifica una proprietà instance_type, il sistema usa defaultinstancetype per distribuire il modello.

Importante

Per la distribuzione del modello MLflow, la richiesta di risorsa richiede almeno 2 core CPU e 4 GB di memoria. In caso contrario, la distribuzione avrà esito negativo.

Convalida della sezione delle risorse

È possibile usare la sezione resources per definire la richiesta di risorsa e il limite delle distribuzioni del modello. Ad esempio:

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>

Se si usa la sezione resources, una definizione di risorsa valida deve soddisfare le regole seguenti. Una definizione di risorsa non valida causa l'esito negativo della distribuzione del modello.

Parametro Obbligatorio o facoltativo Descrizione
requests:
cpu:
Richiesto Valori di stringa, che non possono essere pari a zero o vuoti.
È possibile specificare la CPU in millicore; ad esempio 100m. È anche possibile specificarla come numeri interi. Ad esempio, "1" equivale a 1000m.
requests:
memory:
Richiesto Valori di stringa, che non possono essere pari a zero o vuoti.
È possibile specificare la memoria come numero intero + suffisso; ad esempio per 1024Mi 1024 MiB.
La memoria non può essere inferiore a 1 MB.
limits:
cpu:
Facoltativo
(obbligatorio solo quando è necessaria la GPU)
Valori di stringa, che non possono essere pari a zero o vuoti.
È possibile specificare la CPU in millicore; ad esempio 100m. È anche possibile specificarla come numeri interi. Ad esempio, "1" equivale a 1000m.
limits:
memory:
Facoltativo
(obbligatorio solo quando è necessaria la GPU)
Valori di stringa, che non possono essere pari a zero o vuoti.
È possibile specificare la memoria come numero intero + suffisso; ad esempio per 1024Mi 1.024 MiB.
limits:
nvidia.com/gpu:
Facoltativo
(obbligatorio solo quando è necessaria la GPU)
Valori interi, che non possono essere vuoti e che è possibile specificare solo nella sezione limits.
Per altre informazioni, vedere la documentazione di Kubernetes.
Se è necessaria solo la CPU, è possibile omettere l'intera sezione limits.

Il tipo di istanza è necessario per la distribuzione del modello. Se è stata definita la sezione resources e la suddetta verrà convalidata in base al tipo di istanza, le regole sono le seguenti:

  • Con una definizione di sezione resource valida, i limiti delle risorse devono essere inferiori ai limiti del tipo di istanza. In caso contrario, la distribuzione avrà esito negativo.
  • Se non si definisce un tipo di istanza, il sistema usa defaultinstancetype per la convalida con la sezione resources.
  • Se non si definisce la sezione resources, il sistema usa il tipo di istanza per creare la distribuzione.

Passaggi successivi