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

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

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

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

目标

本教程包含以下过程:

  • 使用预先训练的图表准备模型。
  • 使用不同的优化模式来测试模型的推理速度。
  • 将自定义模型转换为 TensorRT。
  • 设置一个多地区集群,其配置如下:
    • Google Deep Learning VM Image 映像为基础构建而成。这些映像预安装了 TensorFlow、TensorFlow Serving 和 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 和 Cloud Machine Learning API。

    启用 API

工具设置

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

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

准备模型

本部分介绍了如何创建用于运行模型的虚拟机 (VM) 实例,此外还介绍了如何从 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. 将模型上传到 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
      

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

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

设置一个多地区集群

创建集群

现在,您已在 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. 创建一个托管实例组 (MIG)。必须有此托管实例组才能在特定地区中设置多个运行中实例。这些实例是根据上一步生成的实例模板创建的。

    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 Monitoring 页面上有一些指标。

    1. 在 Google Cloud Platform Console 中,转到 Metrics Explorer

      转到 Metrics Explorer

    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 文档