###1. 部署 tensorrtserver
建议使用 docker 部署 tensorrtserver。docker 相关的知识网上很多,自行参考。tensorrtserver 的官方建议的安装如下:
docker pull nvcr.io/nvidia/tensorrtserver:19.08-py3
镜像文件较大,且国内下载很慢,经常断线。所以建议使用阿里云的镜像源,阿里的镜像源是比较动态的,可以到注册账号后登录阿里云搜索 tensorrtserver ,找到合适的源,以下是两个示例:
docker pull registry.cn-beijing.aliyuncs.com/cloudhjc/tensorrtserver:server19.08
docker pull registry.cn-hangzhou.aliyuncs.com/bostenai/tensorrtserver:19.04-py3
下载完镜像后,可以执行 docker images 看下,然后执行命令,启动该镜像的容器:
docker run --rm --shm-size=1g --ulimit memlock=-1 --ulimit stack=67108864 -p8000:8000 -p8001:8001 -p8002:8002 -v/model/repository:/models registry.cn-hangzhou.aliyuncs.com/bostenai/tensorrtserver:19.04-py3 trtserver --model-store=/models
命令的格式如下:
docker run --rm [环境配置] [端口号配置] -v*[本地模型路径]*:/models [镜像名称] trtserver --model-store=/models
如上则启动了一个地址为本机地址,http 端口号为 8000,grpc 端口号为 8001 ,监控端口号为 8002
###2. 验证服务启动
访问 http://ip:8001/api/status ,可以获得服务当前的运行状态,以及模型列表。
访问 http://ip:8002/metrics,可以获得服务的运行日志。
如果上述的 url 都访问正常,则表示服务正常启动了。
###3. 部署模型
虽然,tensorrtserver 自带有模型示例,但是没有 saved_model 的示例,所以我们先自己生成一个 saved_model 模型,如下的 python 脚本可以生成一个矩阵相乘的 saved_model 的模型
import tensorflow as tf
import numpy as np
input0 = tf.placeholder(tf.float32, [None, None], "input0")
input1 = tf.placeholder(tf.float32, [None, None], "input1")
b = tf.Variable(2.0,name='b')
output = tf.matmul(input0, input1, name="matmul")
with tf.compat.v1.Session() as sess:
sess.run(tf.global_variables_initializer())
v = sess.run([output], feed_dict={input0: np.ones([3, 2], np.float32), input1: np.ones([2, 3], np.float32)})
print(v)
print(b)
inp0 = tf.saved_model.utils.build_tensor_info(input0)
inp1 = tf.saved_model.utils.build_tensor_info(input1)
out = tf.saved_model.utils.build_tensor_info(output)
sign = tf.saved_model.signature_def_utils.build_signature_def(
inputs={'input0': inp0, 'input1': inp1},
outputs={'output': out},
method_name=tf.saved_model.signature_constants.PREDICT_METHOD_NAME)
builder = tf.saved_model.builder.SavedModelBuilder("export")
builder.add_meta_graph_and_variables(
sess, [tf.saved_model.tag_constants.SERVING],
signature_def_map={ tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY: sign },
main_op=tf.tables_initializer(),
strip_default_attrs=True)
builder.save()
print ("export end!!")
执行脚本后在同目录下的 export 就会生成一个 saved_model.pb 的模型。
将模型文件(saved_model.pb 和 variables 目录)拷贝到部署 tensorrtserver 的服务器。假设我们的模型路径为 /model/,模型名称为 matmul,那么经过拷贝和重命名后的路径目录结构期望如下:
.
└── matmul
├── 1
│ └── model.savedmodel
│ ├── saved_model.pb
│ └── variables
└── config.pbtxt
即需要在模型路径下创建 matmul 文件夹,并在文件中创建名称为 1 的文件夹,在名称为 1 的文件夹在再创建一个名称为 model.savedmodel 的文件夹,模型文件 saved_model.pb 和 variables 目录保存在 model.savedmodel 文件夹下。这个目录结构中 1 实际上就是 tensorrtserver 定义的模型的版本号。在 matmul 目录下 config.pbtxt 是模型的配置文件,这个文件需要自己编写。
###4. 编写 config.pbtxt
config.pbtxt 是模型访问的配置文件,需要正确编写,否则模型无法正确加载。上面矩阵相乘的 config.pbtxt 内容如下:
name: "matmul"
platform: "tensorflow_savedmodel"
max_batch_size: 0
input [
{
name: "input0"
data_type: TYPE_FP32
dims: [1, 10]
},
{
name: "input1"
data_type: TYPE_FP32
dims: [10, 1]
}
]
output [
{
name: "output"
data_type: TYPE_FP32
dims: [1, 1]
}
]
#####4.1 基本配置
Servable {name: matmul version: 1} cannot be loaded: Internal: unable to load model ‘matmul’, model configuration supports batching but first dimension of tensor ‘input0’ expected by framework is not a variable-size batch dimension: [10]
#####4.2 input 和 ouput 的配置
config.pbtxt 中的 input 和 output 时配置的重中之重,它们需要和模型的输入和输出严格保持一致。所以配置之前,我们需要先查看模型的输入输出信息。通过 saved_model_cli 命令可以查看该信息。saved_model_cli 在安装 tensorflow 之后即有,在系统命令行下执行。
执行命令格式如下(参数是路径,不是名称):
saved_model_cli show --all --dir [saved_model路径]
得到的返回如下
MetaGraphDef with tag-set: 'serve' contains the following SignatureDefs:
signature_def['serving_default']:
The given SavedModel SignatureDef contains the following input(s):
inputs['input0'] tensor_info:
dtype: DT_FLOAT
shape: (-1, -1)
name: input0:0
inputs['input1'] tensor_info:
dtype: DT_FLOAT
shape: (-1, -1)
name: input1:0
The given SavedModel SignatureDef contains the following output(s):
outputs['output'] tensor_info:
dtype: DT_FLOAT
shape: (-1, -1)
name: matmul:0
Method name is: tensorflow/serving/predict
这里需要注意的是,如果执行 saved_model_cli 命令后返回的信息不包含 serve 和 serve 的签名,那么这个模型是不可以运行在 tensorrtserver 上。这点很重要,不是部署的问题,是模型的问题。
得到配置信息之后,我们就可以根据信息进行 input 和 output 的配置了。
nput0 = tf.placeholder(tf.float32, None, "input0")
- tag-set 中不包含 serve ,或者有 serve 标签,但是没有 server 的签名的
- shape 中包含 unkonwn_rank 的
编辑完成 config.pbtxt 后,就可以启动服务了。
执行命令:
docker run --rm --shm-size=1g --ulimit memlock=-1 --ulimit stack=67108864 -p8000:8000 -p8001:8001 -p8002:8002 -v/model/:/models registry.cn-hangzhou.aliyuncs.com/bostenai/tensorrtserver:19.04-py3 trtserver --model-store=/models
启动服务,访问 http://ip:8001/api/status/matmul 得到模型的信息如下:
id: "inference:0"
version: "1.1.0"
uptime_ns: 2190253935560
model_status {
key: "matmul"
value {
config {
name: "matmul"
platform: "tensorflow_savedmodel"
version_policy {
latest {
num_versions: 1
}
}
input {
name: "input0"
data_type: TYPE_FP32
dims: 1
dims: 10
}
input {
name: "input1"
data_type: TYPE_FP32
dims: 10
dims: 1
}
output {
name: "output"
data_type: TYPE_FP32
dims: 1
dims: 1
}
instance_group {
name: "matmul"
count: 1
kind: KIND_CPU
}
default_model_filename: "model.savedmodel"
}
version_status {
key: 1
value {
ready_state: MODEL_READY
}
}
}
}
ready_state: SERVER_READY
看到模型的 ready_state 为 SERVER_READY 表示模型已经处于可以访问的状态了。这时候就可以调用客户端访问该模型了。