发布于: Aug 26, 2022

 

本文建议大家使用 z1d.xlarge 实例类型,其拥有出色的单核性能与内存容量。

 

您可以在 Amazon Web Services 中设置 EC2 实例,借此开启模型编译流程。本文建议大家使用 z1d.xlarge 实例类型,其拥有出色的单核性能与内存容量。在 US East(北弗吉尼亚州)区域内,使用 Amazon Web Services Deep Learning AMI(Ubuntu 18.04)的 29.0 版本(ami-043f9aeaf108ebc37)。此 AMI 预打包有 Neuron SDK 以及 Amazon Web Services Inferentia 所需要的 Neuron 运行时。

关于在 EC2 实例上运行 Amazon Web Services Deep Learning AMI 的更多详细信息,请参阅启动并配置 DLAMI。

在通过 SSH 接入该实例时,您可以激活 aws_neuron_tensorflow_p36 Conda 环境,并将 Neuron 编译器更新至最新版本。编译脚本的正常运行,依赖于 requirements-compile.txt 文件中列出的具体要求。关于编译脚本与需求文件,请参阅 GitHub repo。您可以使用以下代码,将其下载并安装至目标环境当中:

source activate aws_neuron_tensorflow_p36
pip install neuron-cc --upgrade --extra-index-url=https://pip.repos.neuron.amazonaws.com
git clone https://github.com/aws/aws-neuron-sdk.git /tmp/aws-neuron-sdk && cp /tmp/aws-neuron-sdk/src/examples/tensorflow/<name_of_the_new_folder>/* . && rm -rf /tmp/aws-neuron-sdk/
pip install -r requirements-compile.txt

接下来,我们就可以开始编译过程。您可以编译 tf-pose-estimation 网络冻结图,在 GitHub repo 上可以找到。下面将下载到的原始脚本调整为单行 wget 命令:

wget -c --tries=2 $( wget -q -O - http://www.mediafire.com/file/qlzzr20mpocnpa3/graph_opt.pb | grep -o 'http*://download[^"]*' | tail -n 1 ) -O graph_opt.pb

当下载完成之后,运行 convert_graph_opt.py 脚本以为 Amazon Web Services Inferentiav 芯片编译。由于 Neuron 属于提前(AOT)编译器,大家需要在编译之前定义特定的图像大小。您可以使用 — net_resolution 参数(例如 net_resolution=656x368)来调整网络输入图像的分辨率。

编译后的模型可以在推理运行过程中接受任意批次大小的输入。此属性可以对模型的大规模部署进行基准测试;但是,示例 tf-pose-estimation repo 中用于图像及视频处理管道的批次大小设置为 1。

要开始编译流程,请输入以下代码:

python convert_graph_opt.py graph_opt.pb graph_opt_neuron_656x368.pb

编译流程最多可能需要 20 分钟。在此期间,编译器会优化 TensorFlow 图运算并为已保存的模型生成 Amazon Web Services Inferentia 版本。在编译过程中,系统会保留详尽的编译日志,例如:

2020-07-15 21:44:43.008627: I bazel-out/k8-opt/bin/tensorflow/neuron/convert/segment.cc:460] There are 11 ops of 7 different types in the graph that are not compiled by neuron-cc: Const, NoOp, Placeholder, RealDiv, Sub, Cast, Transpose, (For more information see https://github.com/aws/aws-neuron-sdk/blob/master/release-notes/neuron-cc-ops/neuron-cc-ops-tensorflow.md).
INFO:tensorflow:fusing subgraph neuron_op_ed41d2deb8c54255 with neuron-cc
INFO:tensorflow:Number of operations in TensorFlow session: 474
INFO:tensorflow:Number of operations after tf.neuron optimizations: 474
INFO:tensorflow:Number of operations placed on Neuron runtime: 465

在评估编译后的模型性能之前,您需要切换至由 Amazon Web Services Inferentia 芯片提供支持的 EC2 Inf1 实例。要在两个实例之间共享编译完成的模型,请使用以下代码创建一个 S3 存储桶:

aws s3 mb s3://<MY_BUCKET_NAME>
aws s3 cp graph_opt_neuron_656x368.pb s3://<MY_BUCKET_NAME>/graph_model.pb

在将编译完成的 graph_model.pb 模型保存在 S3 存储桶后,我们需要修改 GitHub repo 上的 ML 管道脚本,借此根据图像与视频估计人体姿态。

要设置基准 Inf1 实例,您可以重复以上在 z1d 实例上配置编译的步骤。大家可以使用相同的 AMI,只需要注意将实例类型更改为 inf1.xlarge。本文建议大家使用 g4dn.xlarge 实例,在设置基本不变的情况下,这样的类型选择将帮助我们更直接地将运行在 GPU 上的基础 tf-pose-estimation 模型性能与 Amazon Web Services Inferentia 编译模型进行比较。

通过本文,我们将使用 Jupyter Lab 服务器与目标实例及模型进行交互。关于在 Amazon EC2 上配置 Jupyter Lab 的更多详细信息,请参阅如何设置 Jupyter Notebook 服务器。

 

在登录至 Jupyter Lab 服务器之后,您即可克隆包含有 TensorFlow 版 OpenPose 的 GitHub repo。

在 Jupyter Launcher 页面中的 Other 之下,选择 Terminal。

在终端内,激活包含有 Neuron SDK 的 aws_neuron_tensorflow_p36 环境。环境激活与克隆操作需要使用以下代码:

conda activate aws_neuron_tensorflow_p36
git clone https://github.com/ildoonet/tf-pose-estimation.git
cd tf-pose-estimation

在克隆完成之后,我们建议您按照软件包安装说明进行操作,分步完成 repo 安装。在同一终端屏幕内,您可以通过安装 GitHub repo 中 requirements.txt 文件所列出的 opencv-python 与依赖项进行环境定制。您需要运行两条 pip 命令:第一条命令负责处理 opencv-python;第二条负责完成 requirements.txt 中指定的安装步骤:

pip install opencv-python 
pip install -r requirements.txt

现在,大家可以开始构建 notebook 了。

在 repo 的 root 目录中,选择 Notebook,Environment(conda_aws_neuron_tensorflow_p36)以创建一个新的 Jupyter notebook。在 notebook 的第一个单元格中,导入 run.py 脚本中定义的库——此脚本将作为图像处理的参考管道。在后续单元格中,创建一个记录器以记录基准测试结果。详见以下代码:

import argparse
import logging
import sys
import time

from tf_pose import common
import cv2
import numpy as np
from tf_pose.estimator import TfPoseEstimator
from tf_pose.networks import get_graph_path, model_wh
logger = logging.getLogger('TfPoseEstimatorRun')
logger.handlers.clear()
logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('[%(asctime)s] [%(name)s] [%(levelname)s] %(message)s')
ch.setFormatter(formatter)
logger.addHandler(ch)

定义主要推理函数 main() 与辅助绘图函数 plotter()。这些函数是直接从 run.py 处复制的 OpenPose 推理管道。我们需要对其做出简单修改,即添加 repeats 参数,借此依次运行多个推理步骤并改进对平均模型吞吐量的度量能力(以每张图像的处理秒数为单位):

def main(argString='--image ./images/contortion1.jpg --model cmu', repeats=10):
    parser = argparse.ArgumentParser(description='tf-pose-estimation run')
    parser.add_argument('--image', type=str, default='./images/apink2.jpg')
    parser.add_argument('--model', type=str, default='cmu',
                        help='cmu / mobilenet_thin / mobilenet_v2_large / mobilenet_v2_small')
    parser.add_argument('--resize', type=str, default='0x0',
                        help='if provided, resize images before they are processed. '
                             'default=0x0, Recommends : 432x368 or 656x368 or 1312x736 ')
    parser.add_argument('--resize-out-ratio', type=float, default=2.0,
                        help='if provided, resize heatmaps before they are post-processed. default=1.0')

    args = parser.parse_args(argString.split())

    w, h = model_wh(args.resize)
    if w == 0 or h == 0:
        e = TfPoseEstimator(get_graph_path(args.model), target_size=(432, 368))
    else:
        e = TfPoseEstimator(get_graph_path(args.model), target_size=(w, h))

    # estimate human poses from a single image !
    image = common.read_imgfile(args.image, None, None)
    if image is None:
        logger.error('Image can not be read, path=%s' % args.image)
        sys.exit(-1)

    t = time.time()
    for _ in range(repeats):
        humans = e.inference(image, resize_to_default=(w > 0 and h > 0), upsample_size=args.resize_out_ratio)
    elapsed = time.time() - t

    logger.info('%d times inference on image: %s at %.4f seconds/image.' % (repeats, args.image, elapsed/repeats))

    image = TfPoseEstimator.draw_humans(image, humans, imgcopy=False)
    return image, e
def plotter(image):
    try:
        import matplotlib.pyplot as plt

        fig = plt.figure(figsize=(12,12))
        a = fig.add_subplot(1, 1, 1)
        a.set_title('Result')
        plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
        
    except Exception as e:
        logger.warning('matplitlib error, %s' % e)
        cv2.imshow('result', image)
        cv2.waitKey()

另外,如果您比较喜欢冒险,也可以根据 run_video.py 或 run_directory.py 修改用于推理视频或批量图像的代码结构。本轮演练仅供参考,大家不妨放松心态,尽情尝试!

其中 main() 函数会将 GitHub repo 中 Test Inference 部分描述的参数字符串作为输入。要测试 notebook 的实现效果,请使用一组参考参数(请使用原始下载脚本以确保下载 cmu 模型):

img, e = main('--model cmu --resize 656x368 --image=./images/ski.jpg --resize-out-ratio 2.0')
plotter(img)

日志内容显示,您的第一个多人姿态分析任务已经完成:

‘[TfPoseEstimatorRun] [INFO] 10 times inference on image: ./images/ski.jpg at 1.5624 seconds/image.’

可以看到,当前吞吐量每秒不足一帧(FPS),代表性能表现比较差。在这种情况下,我们实际是未使用 GPU 资源运行 TesnorFlow 图 – model cmu。很多朋友都清楚,这类模型在 CPU 上无法获得最佳运行性能。如果重复设置步骤,并选择使用搭载英伟达 T4 GPU 的 g4dn.xlarge 实例,则结果将大为不同:

‘[TfPoseEstimatorRun] [INFO] 10 times inference on image: ./images/ski.jpg at 0.1708 seconds/image’

结果显示 5.85 FPS,性能得到了显著提升。

 

相关文章