您当前的位置:首页 > 电脑百科 > 人工智能

如何提升Tensorflow服务性能

时间:2019-03-29 13:32:32  来源:  作者:

Tensorflow已经成长为事实上的机器学习(ML)平台,在业界和研究领域都很流行。对Tensorflow的需求和支持促成了大量围绕训练和服务机器学习(ML)模型的OSS库、工具和框架。Tensorflow服务是一个构建在分布式生产环境中用于服务机器学习(ML)模型的推理方面的项目。

今天,我们将重点讨论通过优化预测服务器和客户机来提高延迟的技术。模型预测通常是“在线”操作(在关键的应用程序请求路径上),因此我们的主要优化目标是以尽可能低的延迟处理大量请求。

首先让我们快速概述一下Tensorflow服务。

什么是Tensorflow服务?

Tensorflow Serving提供灵活的服务器架构,旨在部署和服务机器学习(ML)模型。一旦模型被训练过并准备用于预测,Tensorflow服务就需要将模型导出为Servable兼容格式。

Servable是封装Tensorflow对象的中心抽象。例如,模型可以表示为一个或多个可服务对象。因此,Servables是客户机用来执行计算(如推理)的底层对象。可服务的大小很重要,因为较小的模型使用更少的内存、更少的存储空间,并且将具有更快的加载时间。Servables希望模型采用SavedModel格式,以便使用Predict API加载和服务。

如何提升Tensorflow服务性能

 

Tensorflow Serving将核心服务组件放在一起,构建一个gRPC/HTTP服务器,该服务器可以服务多个ML模型(或多个版本)、提供监视组件和可配置的体系结构。

Tensorflow服务与Docker

让我们使用标准Tensorflow服务(无CPU优化)获得基线预测性能延迟指标。

首先,从Tensorflow Docker hub中提取最新的服务镜像:

docker pull tensorflow/serving:latest

出于本文的目的,所有容器都在4核15GB Ubuntu 16.04主机上运行。

将Tensorflow模型导出为SavedModel格式

使用Tensorflow训练模型时,输出可以保存为变量检查点(磁盘上的文件)。可以通过恢复模型检查点或其转换的冻结图(二进制)直接运行推理。

为了使用Tensorflow服务来提供这些模型,必须将冻结图导出为SavedModel格式。Tensorflow文档提供了以SavedModel格式导出训练模型的示例。

我们将使用深度残差网络(ResNet)模型,该模型可用于对ImageNet的1000个类的数据集进行分类。下载预训练的ResNet-50 v2模型(https://github.com/tensorflow/models/tree/master/official/resnet#pre-trained-model),特别是channels_last(NHWC) convolution SavedModel,它通常更适合CPU。

复制下列结构中的RestNet模型目录:

如何提升Tensorflow服务性能

 

Tensorflow Serving期望模型采用数字排序的目录结构来管理模型版本控制。在这种情况下,目录1/对应于模型版本1,其中包含模型体系结构saved_model.pb以及模型权重(变量)的快照。

加载并提供SavedModel

以下命令在docker容器中启动Tensorflow服务模型服务器。为了加载SavedModel,需要将模型的主机目录挂载到预期的容器目录中。

docker run -d -p 9000:8500  
 -v $(pwd)/models:/models/resnet -e MODEL_NAME=resnet 
 -t tensorflow/serving:latest
如何提升Tensorflow服务性能

 

检查容器日志显示,ModelServer正在运行,准备在gRPC和HTTP端点上为resnet模型提供推理请求:

I tensorflow_serving/core/loader_harness.cc:86] Successfully loaded servable version {name: resnet version: 1}
I tensorflow_serving/model_servers/server.cc:286] Running gRPC ModelServer at 0.0.0.0:8500 ... 
I tensorflow_serving/model_servers/server.cc:302] Exporting HTTP/REST API at:localhost:8501 ...
如何提升Tensorflow服务性能

 

预测客户端

Tensorflow Serving将API服务模式定义为协议缓冲区(protobufs)。预测API的gRPC客户端实现打包为tensorflow_serving.apisPython包。我们还需要tensorflowpython包来实现实用功能。

让我们安装依赖项来创建一个简单的客户端:

virtualenv .env && source .env/bin/activate &&  
 pip install numpy grpcio opencv-python tensorflow tensorflow-serving-api
如何提升Tensorflow服务性能

 

该ResNet-50 v2模型期望在channels_last(NHWC)格式的数据结构中使用浮点Tensor输入。因此,使用opencv-python读取输入图像,opencv-python以float32数据类型加载到numpy数组(height x width x channels)中。下面的脚本创建预测客户端存根,将JPEG图像数据加载到numpy数组中,转换为张量原型,提出gRPC预测请求:

#!/usr/bin/env python
from __future__ import print_function
import argparse
import numpy as np
import time
tt = time.time()
import cv2
import tensorflow as tf
from grpc.beta import implementations
from tensorflow_serving.apis import predict_pb2
from tensorflow_serving.apis import prediction_service_pb2
parser = argparse.ArgumentParser(description='incetion grpc client flags.')
parser.add_argument('--host', default='0.0.0.0', help='inception serving host')
parser.add_argument('--port', default='9000', help='inception serving port')
parser.add_argument('--image', default='', help='path to JPEG image file')
FLAGS = parser.parse_args()
def main(): 
 # create prediction service client stub
 channel = implementations.insecure_channel(FLAGS.host, int(FLAGS.port))
 stub = prediction_service_pb2.beta_create_PredictionService_stub(channel)
 
 # create request
 request = predict_pb2.PredictRequest()
 request.model_spec.name = 'resnet'
 request.model_spec.signature_name = 'serving_default'
 
 # read image into numpy array
 img = cv2.imread(FLAGS.image).astype(np.float32)
 
 # convert to tensor proto and make request
 # shape is in NHWC (num_samples x height x width x channels) format
 tensor = tf.contrib.util.make_tensor_proto(img, shape=[1]+list(img.shape))
 request.inputs['input'].CopyFrom(tensor)
 resp = stub.Predict(request, 30.0)
 
 print('total time: {}s'.format(time.time() - tt))
 
if __name__ == '__main__':
 main()
如何提升Tensorflow服务性能

 

使用输入JPEG图像运行客户机的输出如下所示:

python tf_serving_client.py --image=images/pupper.jpg 

total time: 2.56152906418s

输出张量的预测结果为整数值和特征概率

如何提升Tensorflow服务性能

 

对于单个请求,这种预测延迟是不可接受的。然而,这并非完全出乎意料;服务于二进制文件的默认Tensorflow目标是针对最广泛的硬件范围,以涵盖大多数用例。您可能已经从标准的Tensorflow服务容器日志中注意到:

I external/org_tensorflow/tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA

这表示Tensorflow服务二进制文件在不兼容的CPU平台上运行,并未进行优化。

构建CPU优化服务二进制

根据Tensorflow文档,建议从源代码编译Tensorflow,并在运行二进制文件的主机平台的CPU上使用所有可用的优化。Tensorflow构建选项公开了一些标志,以支持构建特定于平台的CPU指令集:

如何提升Tensorflow服务性能

 

在本例中,我们将使用1.13:

USER=$1 
TAG=$2 
TF_SERVING_VERSION_GIT_BRANCH="r1.13" 
git clone --branch="$TF_SERVING_VERSION_GIT_BRANCH" https://github.com/tensorflow/serving
如何提升Tensorflow服务性能

 

Tensorflow服务开发镜像使用Bazel作为构建工具。处理器特定CPU指令集的构建目标可以指定如下:

TF_SERVING_BUILD_OPTIONS="--copt=-mavx --copt=-mavx2 --copt=-mfma --copt=-msse4.1 --copt=-msse4.2"

如果memory是约束,则可以使用--local_resources=2048,.5,1.0 flag 限制内存密集型构建过程的消耗。

以开发镜像为基础构建服务镜像:

#!/bin/bash
USER=$1
TAG=$2
TF_SERVING_VERSION_GIT_BRANCH="r1.13"
git clone --branch="${TF_SERVING_VERSION_GIT_BRANCH}" https://github.com/tensorflow/serving
TF_SERVING_BUILD_OPTIONS="--copt=-mavx --copt=-mavx2 --copt=-mfma --copt=-msse4.1 --copt=-msse4.2"
cd serving && 
 docker build --pull -t $USER/tensorflow-serving-devel:$TAG 
 --build-arg TF_SERVING_VERSION_GIT_BRANCH="${TF_SERVING_VERSION_GIT_BRANCH}" 
 --build-arg TF_SERVING_BUILD_OPTIONS="${TF_SERVING_BUILD_OPTIONS}" 
 -f tensorflow_serving/tools/docker/Dockerfile.devel .
cd serving && 
 docker build -t $USER/tensorflow-serving:$TAG 
 --build-arg TF_SERVING_BUILD_IMAGE=$USER/tensorflow-serving-devel:$TAG 
 -f tensorflow_serving/tools/docker/Dockerfile .
如何提升Tensorflow服务性能

 

ModelServer可以配置tensorflow特定的标志来启用会话并行性。以下选项配置两个线程池来并行执行:

intra_op_parallelism_threads

  • 控制用于并行执行单个操作的最大线程数。
  • 用于并行化具有子操作的操作,这些子操作本质上是独立的。

inter_op_parallelism_threads

  • 控制用于并行执行独立不同操作的最大线程数。
  • Tensorflow Graph上的操作彼此独立,因此可以在不同的线程上运行。

两个选项的默认值都设置为0。这意味着,系统会选择一个合适的数字,这通常需要每个CPU核心有一个线程可用。

接下来,与之前类似地启动服务容器,这次使用从源码构建的docker映像,并使用Tensorflow特定的CPU优化标志:

docker run -d -p 9000:8500  
 -v $(pwd)/models:/models/resnet -e MODEL_NAME=resnet 
 -t $USER/tensorflow-serving:$TAG 
 --tensorflow_intra_op_parallelism=4 
 --tensorflow_inter_op_parallelism=4
如何提升Tensorflow服务性能

 

容器日志不应再显示CPU警告警告。在不更改任何代码的情况下,运行相同的预测请求会使预测延迟降低约35.8%:

python tf_serving_client.py --image=images/pupper.jpg 

total time: 1.64234706879s

提高预测客户端的速度

服务器端已针对其CPU平台进行了优化,但超过1秒的预测延迟似乎仍然过高。

加载tensorflow_serving和tensorflow库的延迟成本很高。每次调用tf.contrib.util.make_tensor_proto也会增加不必要的延迟开销。

我们实际上并不需要的tensorflow或tensorflow_serving包进行预测的请求。

如前所述,Tensorflow预测API被定义为protobufs。因此,可以通过生成必要的tensorflow和tensorflow_servingprotobuf python存根来替换这两个外部依赖项。这避免了在客户端本身上Pull整个Tensorflow库。

首先,摆脱tensorflow和tensorflow_serving依赖关系,并添加grpcio-tools包。

pip uninstall tensorflow tensorflow-serving-api &&  
 pip install grpcio-tools==1.0.0
如何提升Tensorflow服务性能

 

克隆tensorflow/tensorflow和tensorflow/serving存储库并将以下protobuf文件复制到客户端项目中:

如何提升Tensorflow服务性能

 

将上述protobuf文件复制到protos/目录中并保留原始路径:

如何提升Tensorflow服务性能

 

为简单起见,predict_service.proto可以简化为仅实现Predict RPC。这样可以避免引入服务中定义的其他RPC的嵌套依赖项。这是简化的一个例子prediction_service.proto(https://gist.github.com/masroorhasan/8e728917ca23328895499179f4575bb8)。

使用grpcio.tools.protoc以下命令生成gRPC python实现:

PROTOC_OUT=protos/ 
PROTOS=$(find . | grep ".proto$") 
for p in $PROTOS; do 
 python -m grpc.tools.protoc -I . --python_out=$PROTOC_OUT --grpc_python_out=$PROTOC_OUT $p
done
如何提升Tensorflow服务性能

 

现在tensorflow_serving可以删除整个模块:

from tensorflow_serving.apis import predict_pb2 
from tensorflow_serving.apis import prediction_service_pb2
如何提升Tensorflow服务性能

 

并替换为生成的protobufs protos/tensorflow_serving/apis:

from protos.tensorflow_serving.apis import predict_pb2 
from protos.tensorflow_serving.apis import prediction_service_pb2
如何提升Tensorflow服务性能

 

导入Tensorflow库是为了使用辅助函数make_tensor_proto,该函数用于将 python / numpy对象封装为TensorProto对象。

因此,我们可以替换以下依赖项和代码段:

import tensorflow as tf 
...
tensor = tf.contrib.util.make_tensor_proto(features) 
request.inputs['inputs'].CopyFrom(tensor)
如何提升Tensorflow服务性能

 

使用protobuf导入并构建TensorProto对象:

from protos.tensorflow.core.framework import tensor_pb2 
from protos.tensorflow.core.framework import tensor_shape_pb2 
from protos.tensorflow.core.framework import types_pb2 
...
# ensure NHWC shape and build tensor proto
tensor_shape = [1]+list(img.shape) 
dims = [tensor_shape_pb2.TensorShapeProto.Dim(size=dim) for dim in tensor_shape] 
tensor_shape = tensor_shape_pb2.TensorShapeProto(dim=dims) 
tensor = tensor_pb2.TensorProto( 
 dtype=types_pb2.DT_FLOAT,
 tensor_shape=tensor_shape,
 float_val=list(img.reshape(-1)))
request.inputs['inputs'].CopyFrom(tensor)
如何提升Tensorflow服务性能

 

完整的python脚本在这里可用(https://gist.github.com/masroorhasan/0e73a7fc7bb2558c65933338d8194130)。运行更新的初始客户端,该客户端将预测请求发送到优化的Tensorflow服务:

python tf_inception_grpc_client.py --image=images/pupper.jpg 

total time: 0.58314920859s

下图显示了针对标准,优化的Tensorflow服务和客户端超过10次运行的预测请求的延迟:

如何提升Tensorflow服务性能

 

从标准Tensorflow服务到优化版本的平均延迟降低了约70.4%。

优化预测吞吐量

Tensorflow服务也可以配置为高吞吐量处理。优化吞吐量通常是为“脱机”批处理完成的,在“脱机”批处理中并不严格要求延迟界限。

服务器端批处理

延迟和吞吐量之间的权衡取决于支持的batching 参数。

通过设置--enable_batching和--batching_parameters_file标记来启用batching。可以按SessionBundleConfig的定义设置批处理参数(https://github.com/tensorflow/serving/blob/d77c9768e33e1207ac8757cff56b9ed9a53f8765/tensorflow_serving/servables/tensorflow/session_bundle_config.proto)。对于仅CPU系统,请考虑设置num_batch_threads可用的核心数。

在服务器端达到全部批处理后,推理请求在内部合并为单个大请求(张量),并在合并的请求上运行一个Tensorflow会话。在单个会话上运行一批请求是CPU/GPU并行性真正能够发挥作用的地方。

使用Tensorflow服务进行批量处理时需要考虑的一些用例:

  • 使用异步客户机请求填充服务器端上的batches
  • 通过将模型图组件放在CPU / GPU上来加速批处理
  • 在从同一服务器提供多个模型时交错预测请求
  • 强烈建议对“离线”高容量推理处理进行批处理

客户端批处理

在客户端进行批处理将多个输入组合在一起以生成单个请求。

由于ResNet模型需要NHWC格式的输入(第一维是输入数),我们可以将多个输入图像聚合成一个RPC请求:

...
batch = [] 
for jpeg in os.listdir(FLAGS.images_path): 
 path = os.path.join(FLAGS.images_path, jpeg)
 img = cv2.imread(path).astype(np.float32)
 batch.Append(img)
...
batch_np = np.array(batch).astype(np.float32) 
dims = [tensor_shape_pb2.TensorShapeProto.Dim(size=dim) for dim in batch_np.shape] 
t_shape = tensor_shape_pb2.TensorShapeProto(dim=dims) 
tensor = tensor_pb2.TensorProto( 
 dtype=types_pb2.DT_FLOAT,
 tensor_shape=t_shape,
 float_val=list(batched_np.reshape(-1)))
request.inputs['inputs'].CopyFrom(tensor)
如何提升Tensorflow服务性能

 

对于一批N个图像,响应中的输出张量将具有请求批次中相同数量的输入的预测结果,在这种情况下N = 2:

如何提升Tensorflow服务性能

 

硬件加速

对于训练,GPU可以更直观地利用并行化,因为构建深度神经网络需要大量计算才能获得最佳解决方案。

但是,推理并非总是如此。很多时候,当图执行步骤放在GPU设备上时,CNN将会加速推断。然而,选择能够优化价格性能最佳点的硬件需要严格的测试、深入的技术和成本分析。硬件加速并行对于“脱机”推理batch processing更有价值。



Tags:Tensorflow   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
TensorFlow 2.x在构建模型和TensorFlow的整体使用方面提供了很多简单性。那么TF2有什么新变化呢?...【详细内容】
2020-09-23  Tags: Tensorflow  点击:(48)  评论:(0)  加入收藏
介绍深度学习是机器学习的一个分支。深度学习的独特之处在于它带来的准确性和效率。经过大量数据训练后,深度学习系统可以匹配甚至超过人脑的认知能力。PyTorch和TensorFlow...【详细内容】
2020-08-07  Tags: Tensorflow  点击:(126)  评论:(0)  加入收藏
腾讯宣布开源 Transformer 推理加速工具 TurboTransformers。该工具面向自然语言处理领域中 Transformers 相关模型丰富的线上预测场景,据介绍,其在微信、腾讯云、QQ 看点...【详细内容】
2020-04-26  Tags: Tensorflow  点击:(104)  评论:(0)  加入收藏
Tensorflow已经成长为事实上的机器学习(ML)平台,在业界和研究领域都很流行。对Tensorflow的需求和支持促成了大量围绕训练和服务机器学习(ML)模型的OSS库、工具和框架。Tensorflo...【详细内容】
2019-03-29  Tags: Tensorflow  点击:(333)  评论:(0)  加入收藏
▌简易百科推荐
作为数据科学家或机器学习从业者,将可解释性集成到机器学习模型中可以帮助决策者和其他利益相关者有更多的可见性并可以让他们理解模型输出决策的解释。在本文中,我将介绍两个...【详细内容】
2021-12-17  deephub    Tags:AI   点击:(16)  评论:(0)  加入收藏
基于算法的业务或者说AI的应用在这几年发展得很快。但是,在实际应用的场景中,我们经常会遇到一些非常奇怪的偏差现象。例如,Facebook将黑人标记为灵长类动物、城市图像识别系统...【详细内容】
2021-11-08  数据学习DataLearner    Tags:机器学习   点击:(32)  评论:(0)  加入收藏
11月2日召开的世界顶尖科学家数字未来论坛上,2013年诺贝尔化学奖得主迈克尔·莱维特、2014年诺贝尔生理学或医学奖得主爱德华·莫索尔、2007年图灵奖得主约瑟夫·斯发斯基、1986年图灵奖得主约翰·霍普克罗夫特、2002...【详细内容】
2021-11-03  张淑贤  证券时报  Tags:人工智能   点击:(39)  评论:(0)  加入收藏
鉴于物联网设备广泛部署、5G快速无线技术闪亮登场,把计算、存储和分析放在靠近数据生成的地方来处理,让边缘计算有了用武之地。 边缘计算正在改变全球数百万个设备处理和传输...【详细内容】
2021-10-26    计算机世界  Tags:边缘计算   点击:(45)  评论:(0)  加入收藏
这是几位机器学习权威专家汇总的725个机器学习术语表,非常全面了,值得收藏! 英文术语 中文翻译 0-1 Loss Function 0-1损失函数 Accept-Reject Samplin...【详细内容】
2021-10-21  Python部落    Tags:机器学习   点击:(43)  评论:(0)  加入收藏
要开始为开源项目做贡献,有一些先决条件:1. 学习一门编程语言:由于在开源贡献中你需要编写代码才能参与开发,你需要学习任意一门编程语言。根据项目的需要,在后期学习另一种语言...【详细内容】
2021-10-20  TSINGSEE青犀视频    Tags:机器学习   点击:(37)  评论:(0)  加入收藏
SimpleAI.人工智能、机器学习、深度学习还是遥不可及?来这里看看吧~ 从基本的概念、原理、公式,到用生动形象的例子去理解,到动手做实验去感知,到著名案例的学习,到用所学来实现...【详细内容】
2021-10-19  憨昊昊    Tags:神经网络   点击:(47)  评论:(0)  加入收藏
语言是人类思维的基础,当计算机具备了处理自然语言的能力,才具有真正智能的想象。自然语言处理(Natural Language Processing, NLP)作为人工智能(Artificial Intelligence, AI)的核心技术之一,是用计算机来处理、理解以及运...【详细内容】
2021-10-11    36氪  Tags:NLP   点击:(49)  评论:(0)  加入收藏
边缘计算是什么?近年来,物联网设备数量呈线性增长趋势。根据艾瑞测算, 2020年,中国物联网设备的数量达74亿,预计2025年突破150亿个。同时,设备本身也变得越来越智能化,AI与互联网在...【详细内容】
2021-09-22  汉智兴科技    Tags:   点击:(55)  评论:(0)  加入收藏
说起人工智能,大家总把它和科幻电影中的机器人联系起来,而实际上这些科幻场景与现如今的人工智能没什么太大关系。人工智能确实跟人类大脑很相似,但它们的显著差异在于人工智能...【详细内容】
2021-09-17  异步社区    Tags:人工智能   点击:(57)  评论:(0)  加入收藏
相关文章
    无相关信息
最新更新
栏目热门
栏目头条