使用 TensorRT5 和 NVIDIA T4 GPU 运行 TensorFlow 推理工作负载

本教程介绍如何使用在 Google Compute Engine 上运行的 NVIDIA TensorRT5 GPU 对大规模工作负载运行深度学习推理。

在开始之前,需要了解以下基本内容:

  • 深度学习推理是机器学习过程中的一个阶段,该阶段使用经过训练的模型来识别、处理和分类结果。
  • NVIDIA TensorRT 是一个经过优化的平台,用于运行深度学习工作负载。
  • GPU 用于加快数据密集型工作负载(如机器学习和数据处理)的运行速度。Compute Engine 上提供各种 NVIDIA GPU。本教程使用 T4 GPU,因为 T4 GPU 是专为深度学习推理工作负载设计的。

目标

本教程包含以下过程:

  • 使用预先训练的图表准备模型。
  • 使用不同的优化模式来测试模型的推理速度。
  • 将自定义模型转换为 TensorRT。
  • 设置一个多地区集群,其配置如下:
    • Google 深度学习虚拟机映像为基础构建而成。这些映像预安装了 TensorFlow、TensorFlow 服务和 TensorRT5。
    • 启用了自动扩缩功能。本教程中的自动扩缩功能基于 GPU 利用率。
    • 启用了负载平衡。
    • 启用了防火墙。
  • 在多地区集群中运行推理工作负载。

教程设置的高级架构概览

费用

按照本教程操作的费用因教程部分而异。

准备模型并以不同的优化速度测试推理速度的估价约为每天 22.34 美元。此费用根据以下规范估算:

  • 1 个虚拟机实例:n1-standard-8(vCPU:8 个,RAM 30GB)
  • 1 个 NVIDIA Tesla T4 GPU

设置多地区集群的估价约为每天 154.38 美元。此费用根据以下规范估算:

  • 2 个虚拟机实例:n1-standard-16(vCPU:16 个,RAM 60GB)
  • 每个虚拟机实例有 4 个 GPU NVIDIA Tesla T4
  • 每个虚拟机实例有 100 GB SSD
  • 1 条转发规则

这些费用是使用价格计算器估算的。

准备工作

项目设置

  1. 登录您的 Google 帐号。

    如果您还没有 Google 帐号,请注册新帐号

  2. 选择或创建 Google Cloud Platform 项目。

    转到“管理资源”页面

  3. 确保您的 Google Cloud Platform 项目已启用结算功能。

    了解如何启用结算功能

  4. 启用 Compute Engine and Cloud Machine Learning API。

    启用 API

工具设置

要在本教程中使用 gcloud 命令行,请执行以下操作:

  1. 安装或更新为 gcloud 命令行工具的最新版本。
  2. (可选)设置默认区域和地区

准备模型

本部分介绍了如何创建用于运行模型的虚拟机实例。此外还介绍了如何从 Tensorflow 官方模型目录下载模型。

  1. 创建虚拟机实例。

    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. 选择模型。本教程使用 ResNet 模型。此 ResNet 模型根据 TensorFlow 中的 ImageNet 数据集进行训练。

    要将 ResNet 模型下载到虚拟机实例,请运行以下命令:

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

    将 ResNet 模型的位置保存在 $WORKDIR 变量中。

    export WORKDIR=[MODEL_LOCATION]
    

运行推理速度测试

本部分包括以下过程:

  • 设置 ResNet 模型。
  • 以不同的优化模式运行推理测试。
  • 查看推理测试的结果。

测试过程概述

TensorRT 可以提高推理工作负载的执行速度,但量化过程的改进最显著。

模型量化是您用来降低模型权重精确率的过程。例如,如果模型的初始权重是 FP32,您可以将精确率降低到 FP16、INT8 甚至是 INT4。在模型的速度(权重精确率)和准确性之间做出正确的权衡非常重要。幸运的是,TensorFlow 包含的功能就能实现这样的权衡,可测量准确性与速度,或测量其他指标,如吞吐量、延迟时间、节点转换率和总训练时间。

过程

  1. 设置 ResNet 模型。要设置模型,请运行以下命令:

    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. 运行测试。此命令需要一些时间才能完成。

    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
    

    其中:

    • $WORKDIR 是下载 ResNet 模型的目录。
    • --native 参数是要测试的不同量化模式。
  3. 查看结果。测试完成后,您可以比较每种优化模式的推理结果。

    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']
    

    要查看完整结果,请运行以下命令:

    cat $WORKDIR/log.txt
    

    执行结果的屏幕截图

    从结果中,您可以看到 FP32 和 FP16 是相同的。这表示如果您能够熟练运用 TensorRT,便可以立即开始使用 FP16。INT8 显示的结果稍微逊色。

    此外,您还可以看到使用 TensorRT5 运行模型会显示以下结果:

    • 使用 FP32 优化功能可将吞吐量提高 40%:从 314 fps 提高到 440 fps。同时,延迟时间缩短约 30%,从 0.40 毫秒变成 0.28 毫秒。
    • 使用 FP16 优化功能而非原生 TensorFlow 图可将速度提升 214%:从 314 fps 提升到 988 fps。同时,延迟时间缩短 0.12 毫秒,几乎降低 3 倍。
    • 使用 INT8,您可以观察到速度提升 385%(从 314 fps 提升到 1524 fps),而延迟时间缩短为 0.08 毫秒。

将自定义模型转换为 TensorRT

您可以使用 INT8 模型进行此转换。

  1. 下载模型。要将自定义模型转换为 TensorRT 图,您需要一个已保存的模型。要获取已保存的 INT8 ResNet 模型,请运行以下命令:

    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. 使用 TFTools 将模型转换为 TensorRT 图。要使用 TFTools 转换模型,请运行以下命令:

    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"
    

    现在,$WORKDIR/resnet_v2_int8_NCHW/00001 目录中有一个 INT8 模型。

    要确保一切设置都正确,请尝试运行推理测试。

    tensorflow_model_server --model_base_path=$WORKDIR/resnet_v2_int8_NCHW/ --rest_api_port=8888
    
  3. 将模型上传到 Google Cloud Storage。必须执行此步骤,模型才能用在下一部分设置的多地区集群中。要上传模型,请完成以下步骤:

    1. 归档模型。

      tar -zcvf model.tar.gz ./resnet_v2_int8_NCHW/
      
    2. 上传归档。

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

      需要时,您可以通过以下网址从 Google Cloud Storage 获取 INT8 冻结图:

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

设置多地区集群

创建集群

在 Google Cloud Storage 平台上拥有模型后,您就可以创建集群了。

  1. 创建实例模板。实例模板是用于创建新实例的资源。请参阅实例模板

    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
    
    • 此实例模板包含由元数据参数指定的启动脚本。
      • 对使用此模板的每个实例进行创建时,运行此启动脚本。
      • 此启动脚本会执行以下步骤:
        • 安装监控代理,以监控实例上的 GPU 使用情况。
        • 下载模型。
        • 启动推理服务。
      • 在启动脚本中,tf_serve.py 包含推理逻辑。就此示例而言,我根据 TFServe 软件包创建了一个非常小的 Python 文件。
      • 要查看启动脚本,请参阅 startup_inf_script.sh
  2. 创建托管实例组。必须有此托管实例组才能在特定地区中设置多个运行中实例。这些实例是根据上一步生成的实例模板创建的。

    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
    
    • 您可以在支持 T4 GPU 的任何适用地区中创建此实例。请确保您在该地区中具有可用的 GPU 配额
    • 创建实例需要一些时间。您可以通过运行以下命令来查看进度:

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

      实例创建过程的屏幕截图

    • 创建托管实例组后,您应该会看到类似如下的输出:

      运行中实例的屏幕截图

  3. 确认 Google Cloud Platform Stackdriver 页面上有一些指标。

    1. 转到 Stackdriver 页面
    2. 搜索 gpu_utilization

      Stackdriver 启动的屏幕截图

    3. 如果有数据进入,您应该会看到如下内容:

      Stackdriver 运行的屏幕截图

启用自动扩缩

  1. 为托管实例组启用自动扩缩功能。

    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
    

    custom.googleapis.com/gpu_utilization 是指标的完整路径。该示例指定级别 85,这意味着只要 GPU 利用率达到 85,平台就会在我们的组中创建一个新实例。

  2. 测试自动扩缩功能。要测试自动扩缩功能,您需要执行以下步骤:

    1. 通过 SSH 连接到实例。请参阅连接到实例
    2. 使用 gpu-burn 工具向 GPU 增加负载,让 GPU 利用率达到 100% 并保持 600 秒:

      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. 查看 Stackdriver 页面。观察自动扩缩功能。集群通过添加另一个实例来纵向扩容。

      自动扩缩的屏幕截图

    4. 转到 GCP Console 中的“实例组”页面。

      转到“实例组”页面

    5. 点击 deeplearning-instance-group 托管实例组。

    6. 点击“监控”标签页。

      “监控”标签页的屏幕截图

      此时,您的自动扩缩逻辑应该会尝试启动尽可能多的实例以减少负载,但运气不佳。

      而这正是目前发生的状况:

      其他实例的屏幕截图

      此时,您可以停止刻录实例,并观察系统如何缩减。

设置负载平衡器

回顾一下,到目前为止您拥有:

  • 一个经过训练的模型,已使用 TensorRT5 (INT8) 进行优化
  • 一组托管实例。这些实例已根据 GPU 利用率启用自动扩缩

现在,您可以在实例前面创建负载平衡器。

  1. 创建运行状况检查。运行状况检查用于确定后端的特定主机是否可以处理流量。

    export HEALTH_CHECK_NAME="http-basic-check"
    
    gcloud compute health-checks create http $HEALTH_CHECK_NAME \
        --request-path /v1/models/default \
        --port 8888
    
  2. 创建包含实例组和运行状况检查的后端服务。

    1. 创建运行状况检查。

      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. 将实例组添加到新的后端服务。

      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. 设置转发网址。负载平衡器需要知道哪个网址可以转发到后端服务。

    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. 创建负载平衡器。

    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. 将外部 IP 地址添加到负载平衡器。

    export IP4_NAME="lb-ip4"
    
    gcloud compute addresses create $IP4_NAME \
        --ip-version=IPV4 \
        --global
    
  6. 找到分配的 IP。

    gcloud compute addresses list
    
  7. 设置转发规则,告知 GCP 将所有请求从公共 IP 转发到负载平衡器。

    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
    

    创建全局转发规则后,传播您的配置可能需要几分钟的时间。

启用防火墙

  1. 检查您是否具有允许从外部源连接到虚拟机实例的防火墙规则。

    gcloud compute firewall-rules list
    
  2. 如果您没有允许这些连接的防火墙规则,则必须予以创建。要创建防火墙规则,请运行以下命令:

    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
    

运行推理

  1. 您可以使用以下 Python 脚本将图像转换为可以上传到服务器的格式。

    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. 运行推理。

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

清理

为避免因本教程中使用的资源而导致系统向您的 Google Cloud Platform 帐号收取费用,请执行以下操作:

  1. 删除转发规则。

    gcloud compute forwarding-rules delete $FORWARDING_RULE --global
    
  2. 删除 IPV4 地址。

    gcloud compute addresses delete $IP4_NAME --global
    
  3. 删除负载平衡器。

    gcloud compute target-http-proxies delete $LB_NAME
    
  4. 删除转发网址。

    gcloud compute url-maps delete $WEB_MAP_NAME
    
  5. 删除后端服务。

    gcloud compute backend-services delete $WEB_BACKED_SERVICE_NAME --global
    
  6. 删除运行状况检查。

    gcloud compute health-checks delete $HEALTH_CHECK_NAME
    
  7. 删除托管实例组。

    gcloud compute instance-groups managed delete $INSTANCE_GROUP_NAME --region us-central1
    
  8. 删除实例模板。

    gcloud beta compute --project=$PROJECT_NAME instance-templates delete $INSTANCE_TEMPLATE_NAME
    
  9. 删除防火墙规则。

    gcloud compute firewall-rules delete www-firewall-80
    gcloud compute firewall-rules delete www-firewall-8888
    
此页内容是否有用?请给出您的反馈和评价:

发送以下问题的反馈:

此网页
Compute Engine 文档