Inférence sur des instances GPU

Voyez comment utiliser des déploiements de modèle pour effectuer une inférence sur les instances de GPU. Le processeur graphique offre des performances supérieures avec les modèles de calcul intensif par rapport à l'unité centrale.

Les processeurs graphiques sont parfaits pour certains cas d'utilisation de l'inférence liée à l'apprentissage automatique, principalement pour les modèles d'apprentissage profond tels que les grands modèles de langage, la parole et la reconnaissance d'images. Les processeurs graphiques utilisent des capacités de traitement parallèles et une bande passante de mémoire élevée, ce qui leur permet de traiter de grandes quantités de données et des calculs complexes beaucoup plus rapidement que les processeurs traditionnels. Les résultats sont des temps d'inférence beaucoup réduits et des performances améliorées.

Le déploiement de modèles du service de science des données prend en charge le déploiement de modèles sur des formes GPU à l'aide de plusieurs méthodes :

Gestion totale

Le service utilise le serveur d'inférence par défaut pour déployer le modèle sur la forme de GPU sélectionnée. Vous contrôlez l'utilisation du GPU à l'aide du fichier score.py.

Basé sur un conteneur

Utilisez votre propre conteneur personnalisé pour le serveur d'inférence. Utilisez le GPU à partir du conteneur et du fichier score.py.

Serveur d'inférence NVIDIA Triton

Le serveur d'inférence Triton offre une excellente utilisation de GPU et est conçu avec une facilité d'utilisation de GPU à partir de zéro. Vous pouvez utiliser un conteneur Triton lors de la création d'un déploiement de modèle.

Préparer l'artefact de modèle

Le déploiement de modèle nécessite un artefact de modèle stocké dans le catalogue de modèles et que le modèle soit actif. L'score.py de l'artefact de modèle doit exposer une variable de périphérique GPU. La fonction load_model doit déplacer le modèle vers l'appareil GPU sélectionné. Ensuite, la fonction predict doit déplacer les tenseurs d'entrée vers le périphérique GPU. Une fois que l'inférence est calculée sur le périphérique GPU, il doit déplacer le tenseur de sortie vers le CPU avant de revenir de la fonction.

Conseil

Envisagez d'utiliser la trousse SDK ADS pour générer automatiquement un artefact de modèle.

La trousse SDK ADS offre la génération automatique du fichier score.py pris en charge par le processeur graphique pour les cadres PyTorch et TensorFlow.

L'exemple score.py suivant utilise un périphérique GPU disponible pour effectuer une inférence sur un modèle Resnet152 PyTorch :

import numpy as np
import os
import torch
from torch import nn
import io
from PIL import Image
import base64
from random import randint
  
  
Image.MAX_IMAGE_PIXELS = None
  
model_name = 'PyTorch_ResNet152.pth'
  
# get an available GPU device 
def get_torch_device():
    num_devices = torch.cuda.device_count()
    if num_devices == 0:
        return "cpu"
    if num_devices == 1:
        return "cuda:0"
    else:
        return f"cuda:{randint(0, num_devices-1)}"
  
print("Device selected for inference", get_torch_device())
device = torch.device(get_torch_device())
 
def load_model(model_file_name=model_name):
    """
    Loads model from the serialized format
  
    Returns
    -------
    model:  Pytorch model instance
    """
    print(f"Devcie {device}")
    model_dir = os.path.dirname(os.path.realpath(__file__))
    contents = os.listdir(model_dir)
    if model_file_name in contents:
        model.load_state_dict(torch.load(os.path.abspath(model_file_name)))    
        model = model.to(device)
        print(f"model saved to {model.get_device()}")
        return model
    else:
        raise FileNotFoundError(f'{model_file_name} is not found in model directory {model_dir}.')
 
def predict(data, model=load_model()):
    """
    Returns prediction given the model and data to predict
  
    Parameters
    ----------
    model: Model instance returned by load_model API
    data: Data format in json
  
    Returns
    -------
    predictions: Output from scoring server
        Format: {'prediction':output from model.predict method}
  
    """
  
    img_bytes = io.BytesIO(base64.b64decode(data.encode('utf-8')))
    image = Image.open(img_bytes).resize((224, 224))
    arr = np.array(image)
    X = torch.FloatTensor(np.transpose(arr, axes=(2, 0, 1))).unsqueeze(0)
    X = X.to(device)
    with torch.no_grad():
        Y = model(X).to("cpu")
        pred = torch.nn.functional.softmax(Y[0], dim=0).argmax().item()
    return {'prediction': pred}

Environnement Conda avec dépendances d'exécution de modèle

Le fichier runtime.yaml dans l'artefact de modèle doit inclure un environnement Conda qui inclut les dépendances GPU.

Dans l'exemple suivant, le fichier runtime.yaml indique au déploiement du modèle d'extraire un environnement Conda publié du chemin de stockage d'objets défini par la variable d'environnement INFERENCE_ENV_PATH :

MODEL_ARTIFACT_VERSION: '3.0'
MODEL_DEPLOYMENT:
  INFERENCE_CONDA_ENV:
    INFERENCE_ENV_PATH: oci://service-conda-packs@id19sfcrra6z/service_pack/gpu/PyTorch_1.10_for_GPU_on_Python_3.8/1.0/pytorch110_p38_gpu_v1
    INFERENCE_ENV_SLUG: pytorch_pack_v1
    INFERENCE_ENV_TYPE: data_science
    INFERENCE_PYTHON_VERSION: 3.8

Répliques de modèle

Lors de l'utilisation d'un serveur d'inférence géré par un service, les déploiements de modèle chargent plusieurs répliques de modèle sur les cartes GPU disponibles pour obtenir un meilleur débit. Le nombre de répliques de modèle est calculé en fonction

  • Taille du modèle.

  • Mémoire disponible sur la carte GPU.

  • Nombre de cartes GPU.

  • Coeurs d'UC logiques disponibles sur la forme de calcul.

Par exemple, le modèle prend 2 Go dans la mémoire et la forme VM.GPU2.1 est sélectionnée avec 1 carte GPU avec 16 Go de mémoire GPU. Le déploiement de modèle alloue un pourcentage (environ 70 %) de mémoire GPU pour charger les modèles et la mémoire restante est enregistrée pour le calcul à l'exécution lors de l'inférence. Le déploiement du modèle charge cinq répliques sur une carte GPU (taille de 16 * (0,7) / 2 Go du modèle en mémoire). Si 2 cartes sont disponibles, un total de 10 répliques de modèles sont chargées avec 5 modèles dans chaque carte.

Avec les fichiers score.py générés automatiquement, la distribution des répliques de modèle aux cartes GPU est basée sur un algorithme aléatoire, qui place statistiquement un nombre presque égal de répliques à chaque carte. Toutefois, vous pouvez modifier le nombre de répliques à l'aide de la variable d'environnement d'application WEB_CONCURRENCY.

Utilisation de Triton pour l'inférence GPU

Le serveur d'inférence Triton de NVIDIA rationalise et normalise l'inférence d'IA en permettant aux équipes de déployer, d'exécuter et d'adapter des modèles d'IA formés à partir de n'importe quel cadre sur n'importe quel processeur graphique ou infrastructure basée sur l'UC.

Configurez un serveur d'inférence NVIDIA Triton à utiliser avec les déploiements de modèle.

Pour activer l'inférence de GPU, config.pbtxt doit contenir KIND_GPU dans le groupe d'instances. La configuration du groupe d'instances peut également être modifiée pour spécifier le nombre de répliques de chargements d'un modèle sur le périphérique GPU