Einführung in Cloud TPU v5e-Inferenzen

Übersicht und Vorteile

Cloud TPU v5e ist ein von Google entwickelter KI-Beschleuniger, der für Transformer-, Text-zu-Image- und CNN-basiertes Training, Feinabstimmung und Bereitstellung (Inferenz). TPU v5e-Slices können bis zu 256 Chips enthalten.

Bereitstellung bezieht sich auf die Bereitstellung eines trainierten Modells für maschinelles Lernen in einem Produktionsumgebung, in der sie für Inferenz verwendet werden können. Latenz-SLOs sind ein Priorität für die Auslieferung.

In diesem Dokument wird die Bereitstellung eines Modells auf einer TPU mit einem einzelnen Host erläutert. TPU-Slices mit 8 oder weniger Chips haben eine TPU-VM oder einen Host und werden als TPUs mit einem einzelnen Host bezeichnet.

Mehr erfahren

Sie benötigen ein Kontingent für v5e-TPUs. On-Demand-TPUs benötigen tpu-v5s-litepod-serving Kontingent. Reservierte TPUs erfordern ein Kontingent von tpu-v5s-litepod-serving-reserved. Weitere Informationen erhalten Sie vom Cloud-Vertrieb.

Sie benötigen ein Google Cloud-Konto und ein Projekt, um Cloud TPU verwenden zu können. Weitere Informationen Weitere Informationen finden Sie unter Cloud TPU-Umgebung einrichten.

v5e-TPUs werden mithilfe von Ressourcen in der Warteschlange bereitgestellt. Für Weitere Informationen zu verfügbaren V5e-Konfigurationen für die Bereitstellung finden Sie unter Cloud TPU v5e-Typen für die Bereitstellung.

Cloud TPU-Modellinferenz und -bereitstellung

Wie Sie ein Modell für die Inferenz bereitstellen, hängt vom ML-Framework ab, das Ihr Modell war die Sie verfasst haben. TPU v5e unterstützt die Bereitstellung von Modellen, die in JAX, TensorFlow, und PyTorch.

Inferenz und Bereitstellung von JAX-Modellen

So stellen Sie ein Modell auf einer TPU-VM bereit:

  1. Modell in TensorFlow SavedModel serialisieren Format
  2. Das gespeicherte Modell mit dem Inferenzkonverter für die Bereitstellung vorbereiten
  3. Modell mit TensorFlow Serving bereitstellen

SavedModel-Format

Ein SavedModel enthält ein vollständiges TensorFlow-Programm, einschließlich trainierter Parametern und Berechnung. Der ursprüngliche Modellbaucode ist nicht erforderlich. ausgeführt werden soll.

Wenn Ihr Modell in JAX geschrieben wurde, müssen Sie zur Serialisierung jax2tf verwenden. Ihr Modell im SavedModel-Format.

Inferenzkonverter

Der Cloud TPU Inference Converter bereitet und optimiert ein Modell vor, das SavedModel-Format für TPU Inferenz. Sie können den Inferenzkonverter in einer lokalen Shell oder auf Ihrer TPU-VM ausführen. Wir empfehlen die Verwendung Ihrer TPU-VM-Shell, da sie über alle Befehlszeilentools verfügt die zum Ausführen des Konverters erforderlich sind. Weitere Informationen zur Inferenz Converter finden Sie im Nutzerhandbuch zum Inferenzkonverter.

Anforderungen für Inferenzkonverter

  1. Ihr Modell muss aus TensorFlow oder JAX in der SavedModel verwenden.

  2. Sie müssen einen Funktionsalias für die TPU-Funktion definieren. Weitere Informationen finden Sie im Nutzerhandbuch zum Inferenzkonverter. In den Beispielen in diesem Leitfaden wird tpu_func als TPU-Funktionsalias verwendet.

  3. Achten Sie darauf, dass die CPU Ihres Computers Advanced Vector eXtensions (AVX) unterstützt als TensorFlow-Bibliothek (die Abhängigkeit des Cloud TPU Inference Converter) wurde zur Verwendung von AVX-Anweisungen kompiliert. Die meisten CPUs AVX-Support.

Inferenz und Bereitstellung von JAX-Modellen

In diesem Abschnitt wird beschrieben, wie JAX-Modelle mit jax2tf und TensorFlow bereitgestellt werden. Auslieferung.

  1. Verwenden Sie jax2tf, um Ihr Modell im SavedModel-Format zu serialisieren
  2. Gespeichertes Modell mit dem Inferenzkonverter für die Bereitstellung vorbereiten
  3. Modell mit TensorFlow Serving bereitstellen

jax2tf verwenden, um ein JAX-Modell im SavedModel-Format zu serialisieren

Die folgende Python-Funktion zeigt, wie Sie jax2tf in Ihrem Modellcode verwenden:

# Inference function
def model_jax(params, inputs):
  return params[0] + params[1] * inputs

# Wrap the parameter constants as tf.Variables; this will signal to the model
# saving code to save those constants as variables, separate from the
# computation graph.
params_vars = tf.nest.map_structure(tf.Variable, params)

# Build the prediction function by closing over the `params_vars`. If you
# instead were to close over `params` your SavedModel would have no variables
# and the parameters will be included in the function graph.
prediction_tf = lambda inputs: jax2tf.convert(model_jax)(params_vars, inputs)

my_model = tf.Module()
# Tell the model saver what the variables are.
my_model._variables = tf.nest.flatten(params_vars)
my_model.f = tf.function(prediction_tf, jit_compile=True, autograph=False)
tf.saved_model.save(my_model)

Weitere Informationen zu jax2tf finden Sie unter Interaktion zwischen JAX und Cloud TPU.

Das gespeicherte Modell mit dem Inferenzkonverter für die Bereitstellung vorbereiten

Eine Anleitung zur Verwendung des Inferenzkonverters finden Sie in den Leitfaden zum Inferenzkonverter

TensorFlow Serving verwenden

Eine Anleitung zur Verwendung von TensorFlow Serving finden Sie unter TensorFlow-Bereitstellung

Beispiele für die Bereitstellung von JAX-Modellen

Vorbereitung

  1. Docker-Anmeldedaten einrichten und Inference Converter und Cloud TPU abrufen Docker-Image bereitstellen:

    sudo usermod -a -G docker ${USER}
    newgrp docker
    gcloud auth configure-docker \
       us-docker.pkg.dev
    docker pull us-docker.pkg.dev/cloud-tpu-images/inference/tpu-inference-converter-cli:2.13.0
    docker pull us-docker.pkg.dev/cloud-tpu-images/inference/tf-serving-tpu:2.13.0
    
  2. Stellen Sie mit SSH eine Verbindung zu Ihrer TPU-VM her und installieren Sie den Inferenz-Democode:

    gcloud storage cp \
    "gs://cloud-tpu-inference-public/demo" \
    . \
    --recursive
    
  3. Installieren Sie die JAX-Demoabhängigkeiten:

    pip install -r ./demo/jax/requirements.txt
    

Das JAX BERT-Modell für die Inferenz bereitstellen

Sie können das vortrainierte BERT-Modell herunterladen. von Hugging Face.

  1. Exportieren Sie ein TPU-kompatibles TensorFlow-Modell aus einem Flax-BERT-Modell:

    cd demo/jax/bert
    python3 export_bert_model.py
    
  2. Starten Sie den Containercontainer für das Cloud TPU-Modell:

    docker run -t --rm --privileged -d \
      -p 8500:8500 -p 8501:8501 \
      --mount type=bind,source=/tmp/jax/bert_tpu,target=/models/bert \
      -e MODEL_NAME=bert \
      us-docker.pkg.dev/cloud-tpu-images/inference/tf-serving-tpu:2.13.0
    

    Prüfen Sie etwa 30 Sekunden nach dem Start des Containers den Modellserver Container-Log und stellen Sie sicher, dass die gRPC- und HTTP-Server aktiv sind:

    CONTAINER_ID=$(docker ps | grep "tf-serving-tpu" | awk '{print $1}')
    docker logs ${CONTAINER_ID}
    

    Wenn ein Logeintrag mit den folgenden Informationen endet, wird der Server Anfragen bereit sind.

    2023-04-08 00:43:10.481682: I tensorflow_serving/model_servers/server.cc:409] Running gRPC ModelServer at 0.0.0.0:8500 ...
    [warn] getaddrinfo: address family for nodename not supported
    2023-04-08 00:43:10.520578: I tensorflow_serving/model_servers/server.cc:430] Exporting HTTP/REST API at:localhost:8501 ...
    [evhttp_server.cc : 245] NET_LOG: Entering the event loop ...
    
  3. Inferenzanfrage an den Modellserver senden.

    python3 bert_request.py
    

    Die Ausgabe sollte in etwa so aussehen:

    For input "The capital of France is [MASK].", the result is ". the capital of france is paris.."
    For input "Hello my name [MASK] Jhon, how can I [MASK] you?", the result is ". hello my name is jhon, how can i help you?."
    
  4. bereinigen.

    Bereinigen Sie den Docker-Container, bevor Sie weitere Demos ausführen.

    CONTAINER_ID=$(docker ps | grep "tf-serving-tpu" | awk '{print $1}')
    docker stop ${CONTAINER_ID}
    

    Bereinigen Sie die Modellartefakte:

    sudo rm -rf /tmp/jax/
    

JAX Stable Diffusion für die Inferenz bereitstellen

Sie können das vortrainierte Stable Diffusion-Modell herunterladen von Hugging Face.

  1. Laden Sie das Stable Diffusion-Modell in einem TPU-kompatiblen TF2-Modell herunter Format:

    cd demo/jax/stable_diffusion
    python3 export_stable_diffusion_model.py
    
  2. Starten Sie den Cloud TPU-Modellservercontainer für das Modell:

    docker run -t --rm --privileged -d \
      -p 8500:8500 -p 8501:8501 \
      --mount type=bind,source=/tmp/jax/stable_diffusion_tpu,target=/models/stable_diffusion \
      -e MODEL_NAME=stable_diffusion \
      us-docker.pkg.dev/cloud-tpu-images/inference/tf-serving-tpu:2.13.0
    

    Prüfen Sie nach etwa zwei Minuten das Containerlog des Modellservers, um sicherzustellen, auf dem gRPC- und HTTP-Server ausgeführt wird:

    CONTAINER_ID=$(docker ps | grep "tf-serving-tpu" | awk '{print $1}')
    docker logs ${CONTAINER_ID}
    

    Wenn das Protokoll mit den folgenden Informationen endet, bedeutet dies, dass Server für Anfragen bereit sind.

    2023-04-08 00:43:10.481682: I tensorflow_serving/model_servers/server.cc:409] Running gRPC ModelServer at 0.0.0.0:8500 ...
    [warn] getaddrinfo: address family for nodename not supported
    2023-04-08 00:43:10.520578: I tensorflow_serving/model_servers/server.cc:430] Exporting HTTP/REST API at:localhost:8501 ...
    [evhttp_server.cc : 245] NET_LOG: Entering the event loop ...
    
  3. Senden Sie eine Anfrage an den Modellserver.

    python3 stable_diffusion_request.py
    

    Dieses Skript sendet „Gemälde eines Eichhörnchens auf Skateboard in New York“ als Prompt ein. Das Ausgabebild wird als stable_diffusion_images.jpg gespeichert in Ihrem des aktuellen Verzeichnisses.

  4. bereinigen.

    Bereinigen Sie den Docker-Container, bevor Sie weitere Demos ausführen.

    CONTAINER_ID=$(docker ps | grep "tf-serving-tpu" | awk '{print $1}')
    docker stop ${CONTAINER_ID}
    

    Modellartefakte bereinigen

    sudo rm -rf /tmp/jax/
    

TensorFlow bereitstellen

Die folgende Anleitung zeigt, wie Sie Ihren TensorFlow-Code Modell auf TPU-VMs.

TensorFlow-Bereitstellungsworkflow

  1. Laden Sie das TensorFlow Serving-Docker-Image für Ihre TPU-VM herunter.

    Beispiel-Umgebungsvariablen festlegen

    export YOUR_LOCAL_MODEL_PATH=model-path
    export MODEL_NAME=model-name
    # Note: this image name may change later.
    export IMAGE_NAME=us-docker.pkg.dev/cloud-tpu-images/inference/tf-serving-tpu:2.13.0
    

    Docker-Image herunterladen

    docker pull ${IMAGE_NAME}
    
  2. Richten Sie die Docker-Anmeldedaten ein und rufen Sie den Inference Converter ab. TensorFlow-Bereitstellungs-Docker-Image

    sudo usermod -a -G docker ${USER}
    newgrp docker
    gcloud auth configure-docker \
       us-docker.pkg.dev
    docker pull us-docker.pkg.dev/cloud-tpu-images/inference/tpu-inference-converter-cli:2.13.0
    docker pull us-docker.pkg.dev/cloud-tpu-images/inference/tf-serving-tpu:2.13.0
    
  3. Laden Sie den Democode herunter:

    gcloud storage cp \
    "gs://cloud-tpu-inference-public/demo" \
    . \
    --recursive
    
  4. Installieren Sie die TensorFlow-Demoabhängigkeiten:

    pip install -r ./demo/tf/requirements.txt
    
  5. TensorFlow-Modell mit TensorFlow Serving bereitstellen Docker-Image auf der TPU-VM.

    # PORT 8500 is for gRPC model server and 8501 is for HTTP/REST model server.
    docker run -t --rm --privileged -d \
      -p 8500:8500 -p 8501:8501 \
      --mount type=bind,source=${YOUR_LOCAL_MODEL_PATH},target=/models/${MODEL_NAME} \
      -e MODEL_NAME=${MODEL_NAME} \
      ${IMAGE_NAME}
    
  6. Verwenden Sie die Serving Client API, um Ihr Modell abzufragen.

Demo zu TensorFlow ResNet-50 Serving ausführen

  1. Exportieren Sie ein TPU-kompatibles TF2-Modell aus dem Keras ResNet-50-Modell.

    cd demo/tf/resnet-50
    python3 export_resnet_model.py
    
  2. Starten Sie den TensorFlow-Modellservercontainer für das Modell.

    docker run -t --rm --privileged -d \
      -p 8500:8500 -p 8501:8501 \
      --mount type=bind,source=/tmp/tf/resnet_tpu,target=/models/resnet \
      -e MODEL_NAME=resnet \
      us-docker.pkg.dev/cloud-tpu-images/inference/tf-serving-tpu:2.13.0
    

    Prüfen Sie das Containerlog des Modellservers und achten Sie darauf, dass gRPC und HTTP-Server aktiv sind:

    CONTAINER_ID=$(docker ps | grep "tf-serving-tpu" | awk '{print $1}')
    docker logs ${CONTAINER_ID}
    

    Wenn das Protokoll mit den folgenden Informationen endet, bedeutet dies, dass der Server zum Verarbeiten von Anfragen bereit ist. Das dauert etwa 30 Sekunden.

    2023-04-08 00:43:10.481682: I tensorflow_serving/model_servers/server.cc:409] Running gRPC ModelServer at 0.0.0.0:8500 ...
    [warn] getaddrinfo: address family for nodename not supported
    2023-04-08 00:43:10.520578: I tensorflow_serving/model_servers/server.cc:430] Exporting HTTP/REST API at:localhost:8501 ...
    [evhttp_server.cc : 245] NET_LOG: Entering the event loop ...
    
  3. Senden Sie die Anfrage an den Modellserver.

    Das Anforderungsbild ist eine Banane von https://i.imgur.com/j9xCCzn.jpeg .

    python3 resnet_request.py
    

    Die Ausgabe sollte in etwa so aussehen:

    Predict result: [[('n07753592', 'banana', 0.94921875), ('n03532672', 'hook', 0.022338867), ('n07749582', 'lemon', 0.005126953)]]
    
  4. bereinigen.

    Bereinigen Sie den Docker-Container, bevor Sie weitere Demos ausführen.

    CONTAINER_ID=$(docker ps | grep "tf-serving-tpu" | awk '{print $1}')
    docker stop ${CONTAINER_ID}
    

    Bereinigen Sie die Modellartefakte:

    sudo rm -rf /tmp/tf/
    

Inferenz und Bereitstellung von PyTorch-Modellen

Für Modelle, die mit PyTorch geschrieben wurden, gilt folgender Workflow:

  1. Python-Modell-Handler zum Laden und Ableiten mit TorchDynamo schreiben und PyTorch/XLA
  2. Mit TorchModelArchiver ein Modellarchiv erstellen
  3. TorchServe verwenden, um das Modell bereitzustellen

TorchDynamo und PyTorch/XLA

TorchDynamo (Dynamo) ist eine Python-Ebene. JIT-Compiler, mit dem PyTorch-Programme schneller werden. Sie bietet eine saubere API. in die Compiler-Back-Ends eingebunden werden können. Sie ändert dynamisch den Python-Bytecode, vor der Ausführung. In der PyTorch/XLA 2.0-Version gibt es ein experimentelles Back-End für Inferenz und Training mit Dynamo.

Dynamo liefert ein Torch FX-Diagramm (FX). wenn ein Modellmuster erkannt wird und PyTorch/XLA einen Lazy Tensor-Ansatz verwendet. um die FX-Grafik zu kompilieren und die kompilierte Funktion zurückzugeben. Weitere Informationen zu Dynamo:

Hier ist ein kleines Codebeispiel für die Ausführung von Densenet161-Inferenz mit torch.compile.

import torch
import torchvision
import torch_xla.core.xla_model as xm

def eval_model(loader):
  device = xm.xla_device()
  xla_densenet161 = torchvision.models.densenet161().to(device)
  xla_densenet161.eval()
  dynamo_densenet161 = torch.compile(
      xla_densenet161, backend='torchxla_trace_once')
  for data, _ in loader:
    output = dynamo_densenet161(data)

TorchServe

Sie können das bereitgestellte Docker-Image torchserve-tpu zum Bereitstellen Ihrer archivierten Pytorch-Modell auf einer TPU-VM.

Richten Sie die Authentifizierung für Docker ein:

sudo usermod -a -G docker ${USER}
newgrp docker
gcloud auth configure-docker \
    us-docker.pkg.dev

Rufen Sie das Cloud TPU TorchServe-Docker-Image auf Ihre TPU-VM ab:

CLOUD_TPU_TORCHSERVE_IMAGE_URL=us-docker.pkg.dev/cloud-tpu-images/inference/torchserve-tpu:v0.9.0-2.1
docker pull ${CLOUD_TPU_TORCHSERVE_IMAGE_URL}

Modellartefakte erfassen

Zuerst müssen Sie einen Modell-Handler bereitstellen, der den TorchServe-Modellserver-Worker laden Sie Ihr Modell, verarbeiten die Eingabedaten und eine Inferenz ausführen. Sie können die Standard-Inferenz-Handler von TorchServe (Quelle) oder Erstellen Sie Ihren eigenen benutzerdefinierten Modell-Handler gemäß base_handler.py. Möglicherweise müssen Sie auch das trainierte Modell und die Modelldefinitionsdatei bereitstellen.

Im folgenden Densenet 161-Beispiel werden Modellartefakte und der Standardwert Bildklassifikator-Handler von TorchServe bereitgestellt:

  1. Konfigurieren Sie einige Umgebungsvariablen:

    CWD="$(pwd)"
    
    WORKDIR="${CWD}/densenet_161"
    
    mkdir -p ${WORKDIR}/model-store
    mkdir -p ${WORKDIR}/logs
    
  2. Laden Sie Modellartefakte aus dem Bildklassifikatorbeispiel von TorchServe herunter und kopieren Sie sie:

    git clone https://github.com/pytorch/serve.git
    
    cp ${CWD}/serve/examples/image_classifier/densenet_161/model.py ${WORKDIR}
    cp ${CWD}/serve/examples/image_classifier/index_to_name.json ${WORKDIR}
    
  3. Laden Sie die Modellgewichtungen herunter:

    wget https://download.pytorch.org/models/densenet161-8d451a50.pth -O densenet161-8d451a50.pth
    
    mv densenet161-8d451a50.pth ${WORKDIR}
    
  4. Erstellen Sie eine Konfigurationsdatei für das TorchServe-Modell, um das Dynamo-Back-End zu verwenden:

    echo 'pt2: "torchxla_trace_once"' >> ${WORKDIR}/model_config.yaml
    

    Sie sollten die folgenden Dateien und Verzeichnisse sehen:

    >> ls ${WORKDIR}
    model_config.yaml
    index_to_name.json
    logs
    model.py
    densenet161-8d451a50.pth
    model-store
    

Modellarchivdatei generieren

Um Ihr PyTorch-Modell mit Cloud TPU TorchServe bereitzustellen, müssen Sie Ihren Modell-Handler und alle Modellartefakte in einer Modellarchivdatei (*.mar) mit dem Torch Model Archiver.

Generieren Sie mit torch-model-archiver eine Modellarchivdatei:

MODEL_NAME=Densenet161

docker run \
    --privileged  \
    --shm-size 16G \
    --name torch-model-archiver \
    -it \
    -d \
    --rm \
    --mount type=bind,source=${WORKDIR},target=/home/model-server/ \
    ${CLOUD_TPU_TORCHSERVE_IMAGE_URL} \
    torch-model-archiver \
        --model-name ${MODEL_NAME} \
        --version 1.0 \
        --model-file model.py \
        --serialized-file densenet161-8d451a50.pth \
        --handler image_classifier \
        --export-path model-store \
        --extra-files index_to_name.json \
        --config-file model_config.yaml

Die Modellarchivdatei sollte im Modellspeicherverzeichnis generiert werden:

>> ls ${WORKDIR}/model-store
Densenet161.mar

Inferenzanfragen bereitstellen

Jetzt haben Sie die Modellarchivdatei und können den TorchServe-Modellserver starten und Inferenzanfragen bereitstellen.

  1. Starten Sie den TorchServe-Modellserver:

    docker run \
        --privileged  \
        --shm-size 16G \
        --name torchserve-tpu \
        -it \
        -d \
        --rm \
        -p 7070:7070 \
        -p 7071:7071 \
        -p 8080:8080 \
        -p 8081:8081 \
        -p 8082:8082 \
        -p 9001:9001 \
        -p 9012:9012 \
        --mount type=bind,source=${WORKDIR}/model-store,target=/home/model-server/model-store \
        --mount type=bind,source=${WORKDIR}/logs,target=/home/model-server/logs \
        ${CLOUD_TPU_TORCHSERVE_IMAGE_URL} \
        torchserve \
            --start \
            --ncs \
            --models ${MODEL_NAME}.mar \
            --ts-config /home/model-server/config.properties
    
  2. Serverstatus des Abfragemodells:

    curl http://localhost:8080/ping
    

    Wenn der Modellserver aktiv ist, wird Folgendes angezeigt:

    {
      "status": "Healthy"
    }
    

    Verwenden Sie Folgendes, um die Standardversionen des aktuell registrierten Modells abzufragen:

    curl http://localhost:8081/models
    

    Sie sollten das registrierte Modell sehen:

    {
      "models": [
        {
          "modelName": "Densenet161",
          "modelUrl": "Densenet161.mar"
        }
      ]
    }
    

    So laden Sie ein Bild für die Inferenz herunter:

    curl -O https://raw.githubusercontent.com/pytorch/serve/master/docs/images/kitten_small.jpg
    
    mv kitten_small.jpg ${WORKDIR}
    

    So senden Sie eine Inferenzanfrage an den Modellserver:

    curl http://localhost:8080/predictions/${MODEL_NAME} -T ${WORKDIR}/kitten_small.jpg
    

    Die Antwort sieht ungefähr so aus:

    {
      "tabby": 0.47878125309944153,
      "lynx": 0.20393909513950348,
      "tiger_cat": 0.16572578251361847,
      "tiger": 0.061157409101724625,
      "Egyptian_cat": 0.04997897148132324
    }
    
  3. Modellserverlogs

    Greifen Sie mit den folgenden Befehlen auf die Logs zu:

    ls ${WORKDIR}/logs/
    cat ${WORKDIR}/logs/model_log.log
    

    Im Protokoll sollte die folgende Meldung angezeigt werden:

    "Compiled model with backend torchxla\_trace\_once"
    

Bereinigen

Beenden Sie den Docker-Container:

rm -rf serve
rm -rf ${WORKDIR}

docker stop torch-model-archiver
docker stop torchserve-tpu

Profilerstellung

Nachdem Sie die Inferenz eingerichtet haben, können Sie mithilfe von Profilern Analysen erstellen, die Leistung und TPU-Auslastung. Weitere Informationen zur Profilerstellung finden Sie unter: