一些童鞋可能晓得,AWS Inferentia是AWS自行设计研发的AI专用芯片,能够用相较于传统GPU更高的性能和更低的老本进行机器学推理。目前一些AWS EC2实例曾经装备了这块芯片。不过具体来说,它的性能到底有多强?老本又能低多少?本文将通过人体姿势预计的实例向大家展现。

在本文中,咱们将应用AWS Neuron编译一套开源的TensorFlow版本的OpenPose,并针对基于AWS Inferentia的实例对推理性能进行调优。与基于GPU的实例相比,咱们须要在本演练中设置基准测试环境、掂量图像处理管道的吞吐量,并量化该零碎的性价比改良状况。

对于OpenPose

人体姿势预计,属于一类机器学习(ML)与计算机视觉(CV)相结合的技术利用方向,可用于反对行人用意预估、AR和体育赛事中的静止跟踪等多种用例。姿势预计的外围在于辨认图像(关节与关键点)的具体坐标,将这些坐标串连起来以形成一个人的骨骼示意。对身材姿势的精确表白,将成为机器人交互设计乃至静止姿势量化等利用指标的实现前提。

目前市面上存在诸多可用于人体姿势预计的办法,其中OpenPose采取深度学习凭借自下而上的办法(由卡耐基梅隆大学认知计算实验室于2018年公布)吸引到泛滥拥趸。OpenPose是一种多人2D姿势预计模型,其中采纳一种称为“部位亲和域”(PAF)的技术对身材各部位进行关联,并借此在图像上建设起多个独自的骨架构造。在这种自下而上的办法中,模型可能辨认出各个关键点,并据此将骨架构造拼凑在一起。

为了实现这一指标,OpenPose应用了两步式流程。首先,它应用VGG-19模型提取图像特色,并将这些特色传递至并行运行的一对卷积神经网络(CNN)当中。

其中一套CNN负责计算置信度图,借此检测图像中的各个身材部位。另一套CNN则计算PAF,并将各个局部合并起来,形成人体骨骼构造。咱们能够多次重复这些并行分支,借此欠缺置信度图与PAF预测后果。

下图所示,为来自VGG的特色F,此特色被馈送至OpenPose模型的PAF与置信度图分支当中。(起源:应用部位亲和域进行实时多人2D姿势预计)

原始OpenPose代码依赖于Caffe模型与预统计的C++库。出于应用便捷性与可移植性的思考,咱们在本轮演练中应用GitHub repo中的tf-pose-estimation基于TensorFlow 1.15从新实现了OpenPose的神经网络。此Repo还提供ML管道脚本,大家能够用OpenPose对图像及视频进行预处理与后处理。

先决条件

在本轮演练中,须要筹备一个有权拜访AWS治理控制台的AWS账户,同时保障有权限应用公开IP创立Amazon Elastic Compute Cloud (Amazon EC2) 实例和创立Amazon Simple Storage Service (Amazon S3)存储桶。

另外,如果相熟如何应用AWS Deep Learning AMI与Jupyter notebooks中的Conda环境则更好,但并非硬性要求。

对于AWS Inferentia与Neuron SDK

AWS Inferentia芯片是一款由AWS定制构建,旨在提供更高推理性能的芯片计划,可能立足云端实现最低推理老本,并帮忙大家轻松将ML集成至规范应用程序性能当中。

AWS Neuron是一款软件开发套件(SDK),由编译器、运行时以及配置文件工具独特组成,这些工具可进一步优化Inferentia芯片的ML推理性能。Neuron曾经与TensorFlow、PyTorch以及MXNet等风行ML框架顺畅集成,且预装在AWS Deep Learning AMI中。在AWS Inferentia上部署深度学习模型的具体形式,与其余平台上的相似环境无甚区别,能够轻松享受到这款芯片带来的性能晋升与老本优化。

在AWS Neuron GitHub上公布的最新Neuron版本,减少了对更多模型(包含OpenPose)的反对选项,咱们将在后文中重点加以介绍。此外,Neuron新版本还将Neuron PyTorch降级到最新稳定版(1.5.1),容许大家在AWS Inferentia上编译并运行更多模型。

应用Neuron SDK编译TensorFlow OpenPose模型

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

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

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

source activate aws_neuron_tensorflow_p36pip install neuron-cc --upgrade --extra-index-url=https://pip.repos.neuron.amazonaws.comgit 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脚本认为AWS Inferentia芯片编译。因为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图运算并为已保留的模型生成AWS 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-ccINFO:tensorflow:Number of operations in TensorFlow session: 474INFO:tensorflow:Number of operations after tf.neuron optimizations: 474INFO:tensorflow:Number of operations placed on Neuron runtime: 465

在评估编译后的模型性能前,须要切换至由AWS 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

在AWS EC2 Inf1实例上应用Jupyter notebook对推理工夫进行基准测试

在将编译实现的graph_model.pb模型保留在S3存储桶后,咱们须要批改GitHub repo上的ML管道脚本,借此依据图像与视频预计人体姿势。

要设置基准Inf1实例,能够反复以上在z1d实例上配置编译的步骤。大家能够应用雷同的AMI,只须要留神将实例类型更改为inf1.xlarge。本文倡议应用g4dn.xlarge实例,在设置根本不变的状况下,这样的类型抉择将帮忙咱们更间接地将运行在GPU上的根底tf-pose-estimation模型性能与AWS Inferentia编译模型进行比拟。

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

为tf-pose设置Conda环境

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

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

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

conda activate aws_neuron_tensorflow_p36git clone https://github.com/ildoonet/tf-pose-estimation.gitcd tf-pose-estimation

在克隆实现之后,倡议依照软件包装置阐明进行操作,分步实现Repo装置。在同一终端屏幕内,能够通过装置GitHub repo中requirements.txt文件所列出的opencv-python与依赖项进行环境定制。

须要运行两条Pip命令:第一条命令负责解决opencv-python;第二条负责实现requirements.txt中指定的装置步骤:

pip install opencv-pythonpip install -r requirements.txt

当初,大家能够开始构建Notebook了。

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

import argparseimport loggingimport sysimport timefrom tf_pose import commonimport cv2import numpy as npfrom tf_pose.estimator import TfPoseEstimatorfrom tf_pose.networks import get_graph_path, model_whlogger = 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, edef 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,性能失去了显著晋升。

应用Neuron编译实现的CMU模型

到这里,咱们曾经应用了repo自带的模型工件。接下来,咱们换一种形式:不再应用原始下载脚本来获取CMU模型,而是将Neuron编译实现的模型复制到./models/graph/cmu/graph_model.pb,而后再次运行测试:

aws s3 cp s3://<MY_BUCKET_NAME>/graph_opt.pb ./models/graph/cmu/graph_model.pb

如果之前曾经对未经Neuron编译的模型进行过测试,请确保在Notebook上重新启动Python内核。重新启动内核,可能保障敞开所有TensorFlow会话,为基准测试提供齐全等效的空白环境。再次运行同一Notebook,将失去以下日志条目:

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

结果显示,与g4dn.xlarge实例相比,新环境可能在升高约30%经营老本的前提下实现雷同的帧速率。这意味着将工作负载转移至基于AWS Inferentia的实例尽管无奈在吞吐量层面带来直观可见的性能晋升,但却的确具备老本劣势。例如,当迁徙至AWS Inferentia时,Amazon Alexa文本到语音转换团队得以将推理老本升高达50%。

咱们决定分析已编译的图版本,并进一步寻求对OpenPose管道进行端到端推理性能调优的空间。Neuron与TensorFlow相集成之后,可实现对本地配置文件库的拜访。要分析Neuron编译图,咱们应用TensorFlow Python分析器,在estimator办法上检测TensorFlow会话所运行的命令:

from tensorflow.core.protobuf import config_pb2from tensorflow.python.profiler import model_analyzer, option_builderrun_options = config_pb2.RunOptions(trace_level=config_pb2.RunOptions.FULL_TRACE)run_metadata = config_pb2.RunMetadata()peaks, heatMat_up, pafMat_up = self.persistent_sess.run( [self.tensor_peaks, self.tensor_heatMat_up, self.tensor_pafMat_up], feed_dict={ self.tensor_image: [img], self.upsample_size: upsample_size }, options=run_options, run_metadata=run_metadata)options = option_builder.ProfileOptionBuilder.time_and_memory()model_analyzer.profile(self.persistent_sess.graph, run_metadata, op_log=None, cmd='scope', options=options)The model_analyzer.profile method prints on StdErr the time and

其中model_analyzer.profile办法会在StdErr上输入TensorFlow图上各项操作所对应的工夫与内存耗费。应用原始代码,Neuron操作与平滑操作占据整个图运行工夫中的大部分比例。以下StdErr日志输入结果显示,总图运行工夫为108.02毫秒,其中平滑操作消耗43.07毫秒:

node name | requested bytes | total execution time | accelerator execution time | cpu execution time_TFProfRoot (--/16.86MB, --/108.02ms, --/0us, --/108.02ms)… TfPoseEstimator/conv5_2_CPM_L1/weights/neuron_op_ed41d2deb8c54255 (430.01KB/430.01KB, 58.42ms/58.42ms, 0us/0us, 58.42ms/58.42ms)…smoothing (0B/2.89MB, 0us/43.07ms, 0us/0us, 0us/43.07ms) smoothing/depthwise (2.85MB/2.85MB, 43.05ms/43.05ms, 0us/0us, 43.05ms/43.05ms) smoothing/gauss_weight (47.50KB/47.50KB, 18us/18us, 0us/0us, 18us/18us)…

其中,OpenPose中平滑办法提供针对置信度图计算得出的高斯含糊后果。通过对此项计算进行优化,咱们可能从端到端姿势预计当中榨取出更好的性能。咱们将estimator.py脚本上的平滑器filter参数从25批改为5。在应用新配置之后,总运行工夫升高至67.44毫秒,其中平滑计算现在只须要2.37毫秒 —— 工夫节约量达37%!而在g4dn实例上,雷同的优化对于运行工夫简直没有任何影响。大家还能够更改同一参数,并通过本地正本重新安装tf-pose-estimation repo的形式优化端到端管道版本。

咱们应用七种不同的实例类型与大小运行了同一项基准测试,借此评估端到端图像处理管道的性能与推理老本优化成果。为了进行直观比拟,咱们还纳入了Amazon EC2按需实例的计费指标。

结果显示,即便是Inf1实例中最小的xlarge实例,其吞吐量也要比g4dn实例中最强劲的8xlarge实例高2倍,且解决1000张图像的老本仅为后者的十二分之一。比照最优的两个选项,inf1.xlarge和g4dn.xlarge(老本最低的GPU选项),Inf1可能将每1000张图像的解决老本较g4dn.xlarge升高72%,相当于性价比晋升3.57倍。下表整顿了此次基准测试的各项发现:

inf1.xlargeinf1.2xlargeinf1.6xlargeg4dn.xlarge_g4dn.2xlarge_g4dn.4xlarge_g4dn.8xlarge
图像处理工夫(秒/图像)0.07030.06770.06560.17080.15260.14770.1427
吞吐量(FPS)14.2214.7715.245.856.556.777.01
1000张图像处理工夫(秒)70.367.765.6170.8152.6147.7142.7
按需实例价格$ 0.368$ 0.584$ 1.904$ 0.526$ 0.752$ 1.204$ 2.176
每1000张图像处理老本$ 2.176$ 0.011$ 0.035$ 0.025$ 0.032$ 0.049$ 0.086

以下图表,总结了xlarge与2xlarge实例在解决1000张图像时的吞吐量与老本状况。

通过在端到端管道中引入数据并行处理办法,咱们又进一步升高了Inf1实例的图像处理老本并晋升了tf-pose-estimation吞吐量。上表中列出的数值,与繁多AWS Inferentia解决外围(即Neuron外围)的应用形式无关。基准实例中蕴含4个外围,因而仅应用其中1个显然会产生资源节约。咱们应用Python joblib库以比拟毛糙的形式将main ()函数调用实现并发扩大至四个线程当中。这种模式可能将吞吐量晋升至56.88FPS,并将每1000张图像的老本升高至0.002美元以下。这意味着更好的批处理策略能够让OpenPose在AWS Inferentia实例上的运行性价比失去更进一步的改善。

规模较大的CMU模型还能提供更好的姿势预计性能。例如,大家能够在蕴含多重景深与相应拍摄对象的场景下(参见下图),应用Neuron SDK编译模型进行多姿势检测。


平安敞开并进行资源清理

在Amazon EC2管制台上抉择编译与推理实例,而后从Actions下拉菜单中抉择Terminate。编译之后的模型将被保留在s3://_<MY_BUCKET_NAME>_当中以备后续重复使用。如果对实例中的代码做出了更改,也请留神进行保留。实例终止仅会导致存储在实例主卷内的数据失落。

总结
在本文中,咱们分步实现了对OpenPose TensorFlow版开源模型的编译,更新自定义端到端图像处理管道,并体验了可能在EC2 Infi1实例之上对ML推理工夫做出剖析及深度优化的工具。在调优之后,Neuron编译的TensorFlow模型较现有费率最低的GPU实例实现72%的老本节约,且性能仍旧保持一致。本文中论述的各项操作步骤,也实用于其余ML模型类型与框架。对于更多详细信息,请参阅AWS Neuron SDK GitHub repo。

感兴趣的敌人能够参阅对于AWS Inferentia芯片与Amazon EC2 Inf1实例的更多详细信息,应用Neuron SDK在AWS Inferentia上运行本人的定制化ML管道。