Como executar cargas de trabalho de inferência do TensorFlow com a TensorRT5 e a GPU NVIDIA T4

Neste tutorial, mostramos como executar inferências de aprendizado profundo em cargas de trabalho de grande escala usando GPUs NVIDIA TensorRT5 em execução no Google Compute Engine.

Antes de começar, veja alguns fundamentos:

  • A inferência de aprendizado profundo é o estágio no processo de machine learning em que um modelo treinado é usado para reconhecer, processar e classificar os resultados.
  • O NVIDIA TensorRT é uma plataforma otimizada para executar cargas de trabalho de aprendizado profundo.
  • As GPUs são usadas para acelerar cargas de trabalho com uso intensivo de dados, como machine learning e processamento de dados. Uma variedade de GPUs NVIDIA está disponível no Compute Engine. Este tutorial usa GPUs T4, já que elas são desenvolvidas especificamente para cargas de trabalho de inferência de aprendizado profundo.

Objetivos

Neste tutorial, são abordados os seguintes procedimentos:

  • Como preparar um modelo usando um gráfico pré-treinado.
  • Como testar a velocidade de inferência de um modelo com diferentes modos de otimização.
  • Como converter um modelo personalizado em TensorRT.
  • Como configurar um cluster de várias zonas. Esse cluster é configurado da seguinte maneira:
    • Baseado nas imagens de VM de aprendizado profundo do Google. Essas imagens são pré-instaladas com o TensorFlow, o TensorFlow Serving e a TensorRT5.
    • Escalonamento automático ativado. Neste tutorial, o escalonamento automático é baseado na utilização da GPU.
    • Balanceamento de carga ativado.
    • Firewall ativado.
  • Como executar uma carga de trabalho de inferência no cluster de várias zonas.

Visão geral de arquitetura de alto nível da configuração do tutorial

Custos

O custo de execução deste tutorial varia por seção.

O preço estimado para preparar seu modelo e testar as velocidades de inferência em diferentes velocidades de otimização é de aproximadamente US$ 22,34 por dia. Esse custo é estimado com base nas especificações a seguir:

  • 1 instância da VM: n1-standard-8 (vCPUs: 8, 30 GB de RAM)
  • 1 GPU NVIDIA Tesla T4

O preço estimado para configurar seu cluster de várias zonas é de aproximadamente US$ 154,38 por dia. Esse custo é estimado com base nas especificações a seguir:

  • 2 instâncias de VM: n1-standard-16 (vCPUs: 16, 60 GB de RAM)
  • 4 GPUs NVIDIA Tesla T4 para cada instância de VM
  • SSD de 100 GB para cada instância de VM
  • 1 regra de encaminhamento

Esses custos foram estimados usando a calculadora de preços.

Antes de começar

Configurar o projeto

  1. Faça login na sua Conta do Google.

    Se você ainda não tiver uma, inscreva-se.

  2. Selecione ou crie um projeto do GCP.

    Acessar a página Gerenciar recursos

  3. Verifique se o faturamento foi ativado para o projeto.

    Saiba como ativar o faturamento

  4. Ativar Compute Engine and Cloud Machine Learning APIs.

    Ativar as APIs

Configuração de ferramentas

Para usar a linha de comando do gcloud neste tutorial:

  1. Instale ou atualize a versão mais recente da ferramenta de linha de comando do gcloud.
  2. (Opcional) Defina uma região e uma zona padrão.

Como preparar o modelo

Esta seção mostra a criação de uma instância de VM usada para executar o modelo. Ela também explica como fazer o download de um modelo do catálogo de modelos oficiais do Tensorflow.

  1. Crie a instância da VM.

    export IMAGE_FAMILY="tf-1-12-cu100"
    export ZONE="us-central1-b"
    export INSTANCE_NAME="model-prep"
    gcloud compute instances create $INSTANCE_NAME \
        --zone=$ZONE \
        --image-family=$IMAGE_FAMILY \
        --machine-type=n1-standard-8 \
        --image-project=deeplearning-platform-release \
        --maintenance-policy=TERMINATE \
        --accelerator="type=nvidia-tesla-t4,count=1" \
        --metadata="install-nvidia-driver=True"
    
  2. Selecione um modelo. Este tutorial usa o modelo ResNet, que é treinado no conjunto de dados do ImageNet que está no TensorFlow.

    Para fazer o download do modelo ResNet para sua instância de VM, execute o seguinte comando:

    wget -q http://download.tensorflow.org/models/official/resnetv2_imagenet_frozen_graph.pb
    

    Salve o local do modelo ResNet na variável $WORKDIR.

    export WORKDIR=[MODEL_LOCATION]
    

Como executar o teste de velocidade de inferência

Esta seção abrange os seguintes procedimentos:

  • Como configurar o modelo ResNet.
  • Como executar testes de inferência em diferentes modos de otimização.
  • Como revisar os resultados dos testes de inferência.

Visão geral do processo de teste

O TensorRT pode melhorar a velocidade de desempenho para cargas de trabalho de inferência. No entanto, a melhoria mais significativa é proveniente do processo de quantização.

A quantização de modelo é o processo pelo qual você reduz a precisão dos pesos de um modelo. Por exemplo, se o peso inicial de um modelo for FP32, será possível reduzir a precisão para FP16, INT8 ou até mesmo INT4. É importante escolher o ajuste correto entre a velocidade (precisão de pesos) e a acurácia de um modelo. Felizmente, o TensorFlow inclui uma funcionalidade que faz exatamente isso medindo acurácia versus velocidade ou outras métricas, como capacidade, latência, taxas de conversão de nós e tempo total de treinamento.

Procedimento

  1. Configure o modelo ResNet. Para configurar o modelo, execute os seguintes comandos:

    git clone https://github.com/tensorflow/models.git
    cd models
    git checkout f0e10716160cd048618ccdd4b6e18336223a172f
    touch research/__init__.py
    touch research/tensorrt/__init__.py
    cp research/tensorrt/labellist.json .
    cp research/tensorrt/image.jpg ..
    
  2. Execute o teste. Este comando leva algum tempo para terminar.

    python -m research.tensorrt.tensorrt \
        --frozen_graph=$WORKDIR/resnetv2_imagenet_frozen_graph.pb \
        --image_file=$WORKDIR/image.jpg \
        --native --fp32 --fp16 --int8 \
        --output_dir=$WORKDIR
    

    em que:

    • $WORKDIR é o diretório no qual você fez o download do modelo ResNet.
    • Os argumentos --native são os diferentes modos de quantização a serem testados.
  3. Revise os resultados. Quando o teste é concluído, é possível fazer uma comparação dos resultados de inferência para cada modo de otimização.

    Predictions:
    Precision:  native [u'seashore, coast, seacoast, sea-coast', u'promontory, headland, head, foreland', u'breakwater, groin, groyne, mole, bulwark, seawall, jetty',     u'lakeside, lakeshore', u'grey whale, gray whale, devilfish, Eschrichtius gibbosus, Eschrichtius robustus']
    Precision:  FP32 [u'seashore, coast, seacoast, sea-coast', u'promontory, headland, head, foreland', u'breakwater, groin, groyne, mole, bulwark, seawall, jetty', u'lakeside,   lakeshore', u'sandbar, sand bar']
    Precision:  FP16 [u'seashore, coast, seacoast, sea-coast', u'promontory, headland, head, foreland', u'breakwater, groin, groyne, mole, bulwark, seawall, jetty', u'lakeside,   lakeshore', u'sandbar, sand bar']
    Precision:  INT8 [u'seashore, coast, seacoast, sea-coast', u'promontory, headland, head, foreland', u'breakwater, groin, groyne, mole, bulwark, seawall, jetty', u'grey         whale, gray whale, devilfish, Eschrichtius gibbosus, Eschrichtius robustus', u'lakeside, lakeshore']
    

    Para ver os resultados completos, execute o seguinte comando:

    cat $WORKDIR/log.txt
    

    Captura de tela dos resultados de desempenho

    Nos resultados, é possível ver que FP32 e FP16 são idênticos. Isso significa que se você estiver confortável trabalhando com o TensorRT, poderá definitivamente começar a usar o FP16 imediatamente. O INT8 mostra resultados um pouco piores.

    Além disso, é possível ver que a execução do modelo com a TensorRT5 mostra os seguintes resultados:

    • Usar a otimização do FP32 melhora o rendimento em 40%, de 314 fps para 440 fps. Ao mesmo tempo, a latência diminui em aproximadamente 30% passando de 0,28ms para 0,40ms.
    • Usar a otimização do FP16, em vez do gráfico nativo do TensorFlow, aumenta a velocidade em 214% de 314 fps para 988 fps. Ao mesmo tempo, a latência diminui em 0,12ms, um decréscimo de quase 3 vezes.
    • Ao usar o INT8, observa-se uma aceleração de 385% de 314 fps para 1.524 fps com a diminuição da latência para 0,08ms.

Como converter um modelo personalizado em TensorRT

Para esta conversão, é possível usar um modelo INT8.

  1. Faça o download do modelo. Para converter um modelo personalizado em um gráfico TensorRT, você precisa de um modelo salvo. Para conseguir um modelo ResNet INT8 salvo, execute o seguinte comando:

    wget http://download.tensorflow.org/models/official/20181001_resnet/savedmodels/resnet_v2_fp32_savedmodel_NCHW.tar.gz
    tar -xzvf resnet_v2_fp32_savedmodel_NCHW.tar.gz
    
  2. Converta o modelo no gráfico TensorRT usando o TFTools. Para converter o modelo usando o TFTools, execute o seguinte comando:

    git clone https://github.com/GoogleCloudPlatform/ml-on-gcp.git
    cd ml-on-gcp/dlvm/tools
    python ./convert_to_rt.py \
        --input_model_dir=$WORKDIR/resnet_v2_fp32_savedmodel_NCHW/1538687196 \
        --output_model_dir=$WORKDIR/resnet_v2_int8_NCHW/00001 \
        --batch_size=128 \
        --precision_mode="INT8"
    

    Agora você tem um modelo INT8 no diretório $WORKDIR/resnet_v2_int8_NCHW/00001.

    Para garantir que tudo esteja configurado corretamente, tente executar um teste de inferência.

    tensorflow_model_server --model_base_path=$WORKDIR/resnet_v2_int8_NCHW/ --rest_api_port=8888
    
  3. Faça o upload do modelo para o Google Cloud Storage. Essa etapa é necessária para que o modelo possa ser usado a partir do cluster de várias zonas que será criado na próxima seção. Para fazer o upload do modelo, conclua as seguintes etapas:

    1. Arquive o modelo.

      tar -zcvf model.tar.gz ./resnet_v2_int8_NCHW/
      
    2. Faça o upload do arquivo.

      export GCS_PATH=<gcs_path>
      gsutil cp model.tar.gz $GCS_PATH
      

      Se necessário, é possível conseguir um gráfico congelado do INT8 do Google Cloud Storage neste URL:

      gs://cloud-samples-data/dlvm/t4/model.tar.gz
      

Como configurar um cluster de várias zonas

Crie o cluster

Agora que você tem um modelo na plataforma do Google Cloud Storage, é possível criar um cluster.

  1. Crie um modelo de instância. Esse modelo é um recurso útil para criar novas instâncias. Consulte Modelos de instância.

    export INSTANCE_TEMPLATE_NAME="tf-inference-template"
    export IMAGE_FAMILY="tf-1-12-cu100"
    export PROJECT_NAME="your_project_name"
    
    gcloud beta compute --project=$PROJECT_NAME instance-templates create $INSTANCE_TEMPLATE_NAME \
         --machine-type=n1-standard-16 \
         --maintenance-policy=TERMINATE \
         --accelerator=type=nvidia-tesla-t4,count=4 \
         --min-cpu-platform=Intel\ Skylake \
         --tags=http-server,https-server \
         --image-family=$IMAGE_FAMILY \
         --image-project=deeplearning-platform-release \
         --boot-disk-size=100GB \
         --boot-disk-type=pd-ssd \
         --boot-disk-device-name=$INSTANCE_TEMPLATE_NAME \
         --metadata startup-script-url=gs://cloud-samples-data/dlvm/t4/start_agent_and_inf_server_4.sh
    
    • Este modelo de instância inclui um script de inicialização especificado pelo parâmetro de metadados.
      • Esse script de inicialização é executado durante a criação da instância em todas as instâncias que usam esse modelo.
      • Este script de inicialização executa as seguintes etapas:
        • Instala um agente de monitoramento que monitora o uso da GPU na instância.
        • Faz o download do modelo.
        • Inicia o serviço de inferência.
      • No script de inicialização, tf_serve.py contém a lógica de inferência. Neste exemplo, criamos um arquivo Python muito pequeno com base no pacote TFServe.
      • Para ver o script de inicialização, consulte startup_inf_script.sh.
  2. Crie um grupo de instâncias gerenciadas. Esse grupo é necessário para configurar várias instâncias em execução em zonas específicas. As instâncias são criadas com base no modelo de instância gerado na etapa anterior.

    export INSTANCE_GROUP_NAME="deeplearning-instance-group"
    export INSTANCE_TEMPLATE_NAME="tf-inference-template"
    gcloud compute instance-groups managed create $INSTANCE_GROUP_NAME \
        --template $INSTANCE_TEMPLATE_NAME \
        --base-instance-name deeplearning-instances \
        --size 2 \
        --zones us-central1-a,us-central1-b
    
    • É possível criar esta instância em qualquer zona disponível compatível com GPUs T4. Verifique se você tem cotas de GPU disponíveis na zona.
    • A criação da instância leva algum tempo. É possível assistir ao progresso executando o seguinte comando:

      export INSTANCE_GROUP_NAME="deeplearning-instance-group"
      
      gcloud compute instance-groups managed list-instances $INSTANCE_GROUP_NAME --region us-central1
      

      Captura de tela da criação da instância

    • Quando o grupo de instâncias gerenciadas é criado, você precisa ver uma saída semelhante à seguinte:

      Captura de tela da instância em execução

  3. Confirme se as métricas estão disponíveis na página do Stackdriver do Google Cloud Platform.

    1. Vá para a página do Stackdriver.
    2. Pesquise por gpu_utilization.

      Captura de tela da iniciação do Stackdriver

    3. Se os dados estiverem entrando, você verá algo como:

      Captura de tela do Stackdriver em execução

Ativar escalonamento automático

  1. Ative o escalonamento automático para o grupo de instâncias gerenciadas.

    export INSTANCE_GROUP_NAME="deeplearning-instance-group"
    
    gcloud compute instance-groups managed set-autoscaling $INSTANCE_GROUP_NAME \
        --custom-metric-utilization metric=custom.googleapis.com/gpu_utilization,utilization-target-type=GAUGE,utilization-target=85 \
        --max-num-replicas 4 \
        --cool-down-period 360 \
        --region us-central1
    

    O caminho completo para a nossa métrica é custom.googleapis.com/gpu_utilization. A amostra especifica o nível 85. Isso significa que sempre que a utilização da GPU atingir 85, a plataforma criará uma nova instância no grupo.

  2. Teste o escalonamento automático. Para isso, execute as seguintes etapas:

    1. SSH para a instância. Consulte Como se conectar a instâncias.
    2. Use a ferramenta gpu-burn para que sua GPU carregue em 100% de utilização por 600 segundos:

      git clone https://github.com/GoogleCloudPlatform/ml-on-gcp.git
      cd ml-on-gcp/third_party/gpu-burn
      git checkout c0b072aa09c360c17a065368294159a6cef59ddf
      make
      ./gpu_burn 600 > /dev/null &
      
    3. Consulte a página do Stackdriver. Observe o escalonamento automático. Ao adicionar mais uma instância, o cluster é escalonado.

      Captura de tela do escalonamento automático

    4. Acesse a página "Grupos de instâncias" no Console do GCP.

      Acessar a página "Grupos de instâncias"

    5. Clique no grupo de instâncias gerenciadas deeplearning-instance-group.

    6. Clique na guia de monitoramento.

      Captura de tela da guia de monitoramento

      Nesse ponto, sua lógica de escalonamento automático tentará girar o máximo possível de instâncias para reduzir a carga, mas sem sucesso.

      É exatamente isso que está acontecendo:

      Captura de tela de instâncias adicionais

      Nesse ponto, é possível parar de gravar instâncias e observar como o sistema é reduzido.

Configurar um balanceador de carga

Vamos recapitular o que você tem até o momento:

  • Um modelo treinado, otimizado com a TensorRT5 (INT8).
  • Um grupo de instâncias gerenciadas. Essas instâncias têm o recurso de escalonamento automático com base na utilização da GPU ativada.

Agora é possível criar um balanceador de carga na frente das instâncias.

  1. Crie verificações de integridade. Essas verificações são usadas para determinar se um determinado host em nosso back-end pode disponibilizar o tráfego.

    export HEALTH_CHECK_NAME="http-basic-check"
    
    gcloud compute health-checks create http $HEALTH_CHECK_NAME \
        --request-path /v1/models/default \
        --port 8888
    
  2. Crie um serviço de back-end que inclua um grupo de instâncias e uma verificação de integridade.

    1. Crie a verificação de integridade.

      export HEALTH_CHECK_NAME="http-basic-check"
      export WEB_BACKED_SERVICE_NAME="tensorflow-backend"
      
      gcloud compute backend-services create $WEB_BACKED_SERVICE_NAME \
          --protocol HTTP \
          --health-checks $HEALTH_CHECK_NAME \
          --global
      
    2. Adicione o grupo de instâncias ao novo serviço de back-end.

      export INSTANCE_GROUP_NAME="deeplearning-instance-group"
      export WEB_BACKED_SERVICE_NAME="tensorflow-backend"
      
      gcloud compute backend-services add-backend $WEB_BACKED_SERVICE_NAME \
          --balancing-mode UTILIZATION \
          --max-utilization 0.8 \
          --capacity-scaler 1 \
          --instance-group $INSTANCE_GROUP_NAME \
          --instance-group-region us-central1 \
          --global
      
  3. Configure o URL de encaminhamento. O balanceador de carga precisa saber qual URL pode ser encaminhado para os serviços de back-end.

    export WEB_BACKED_SERVICE_NAME="tensorflow-backend"
    export WEB_MAP_NAME="map-all"
    
    gcloud compute url-maps create $WEB_MAP_NAME \
        --default-service $WEB_BACKED_SERVICE_NAME
    
  4. Crie o balanceador de carga.

    export WEB_MAP_NAME="map-all"
    export LB_NAME="tf-lb"
    
    gcloud compute target-http-proxies create $LB_NAME \
        --url-map $WEB_MAP_NAME
    
  5. Adicione um endereço IP externo ao balanceador de carga.

    export IP4_NAME="lb-ip4"
    
    gcloud compute addresses create $IP4_NAME \
        --ip-version=IPV4 \
        --global
    
  6. Encontre o IP que está alocado.

    gcloud compute addresses list
    
  7. Configure a regra de encaminhamento que orienta o GCP a encaminhar todas as solicitações do IP público para o balanceador de carga.

    export IP=$(gcloud compute addresses list | grep ${IP4_NAME} | awk '{print $2}')
    export LB_NAME="tf-lb"
    export FORWARDING_RULE="lb-fwd-rule"
    
    gcloud compute forwarding-rules create $FORWARDING_RULE \
        --address $IP \
        --global \
        --target-http-proxy $LB_NAME \
        --ports 80
    

    Após a criação das regras de encaminhamento global, poderá levar alguns minutos até a configuração ser propagada.

Ativar firewall

  1. Verifique se você tem regras de firewall que permitem conexões de fontes externas às instâncias de VM.

    gcloud compute firewall-rules list
    
  2. Se você não tiver regras de firewall que permitam essas conexões, precisará criá-las. Para criar regras de firewall, execute os seguintes comandos:

    gcloud compute firewall-rules create www-firewall-80 \
        --target-tags http-server --allow tcp:80
    
    gcloud compute firewall-rules create www-firewall-8888 \
        --target-tags http-server --allow tcp:8888
    

Como executar uma inferência

  1. É possível usar o script python a seguir para converter imagens em um formato que pode ser carregado no servidor.

    from PIL import Image
    import numpy as np
    import json
    import codecs
    <br>
    img = Image.open("image.jpg").resize((240, 240))
    img_array=np.array(img)
    result = {
           "instances":[img_array.tolist()]
            }
    file_path="/tmp/out.json"
    print(json.dump(result, codecs.open(file_path, 'w', encoding='utf-8'), separators=(',', ':'), sort_keys=True, indent=4))
    
  2. Execute a inferência.

    curl -X POST $IP/v1/models/default:predict -d @/tmp/out.json
    

Como limpar

Para evitar cobranças dos recursos usados neste tutorial na conta do Google Cloud Platform:

  1. Exclua as regras de encaminhamento.

    gcloud compute forwarding-rules delete $FORWARDING_RULE --global
    
  2. Exclua o endereço IPV4.

    gcloud compute addresses delete $IP4_NAME --global
    
  3. Exclua o balanceador de carga.

    gcloud compute target-http-proxies delete $LB_NAME
    
  4. Exclua o URL de encaminhamento.

    gcloud compute url-maps delete $WEB_MAP_NAME
    
  5. Exclua o serviço de back-end.

    gcloud compute backend-services delete $WEB_BACKED_SERVICE_NAME --global
    
  6. Exclua as verificações de integridade.

    gcloud compute health-checks delete $HEALTH_CHECK_NAME
    
  7. Exclua o grupo de instâncias gerenciadas.

    gcloud compute instance-groups managed delete $INSTANCE_GROUP_NAME --region us-central1
    
  8. Exclua o modelo de instância.

    gcloud beta compute --project=$PROJECT_NAME instance-templates delete $INSTANCE_TEMPLATE_NAME
    
  9. Exclua as regras do firewall.

    gcloud compute firewall-rules delete www-firewall-80
    gcloud compute firewall-rules delete www-firewall-8888
    
Esta página foi útil? Conte sua opinião sobre:

Enviar comentários sobre…

Documentação do Compute Engine