diff --git a/README_CN.md b/README_CN.md index 47e4461..0f0aa5d 100644 --- a/README_CN.md +++ b/README_CN.md @@ -3,14 +3,10 @@ [View English](./README.md) - [概述](#概述) -- [安装部署](#安装部署) - - [安装MindSpore Serving](#安装MindSpore-Serving) +- [安装](#安装) + - [安装Serving](#安装Serving) - [配置环境变量](#配置环境变量) - - [部署MindSpore Serving](#部署MindSpore-Serving) - [快速入门](#快速入门) - - [导出模型](#导出模型) - - [部署Serving推理服务](#部署serving推理服务) - - [执行推理](#执行推理) - [文档](#文档) - [开发者教程](#开发者教程) - [社区](#社区) @@ -34,15 +30,15 @@ MindSpore Serving是一个轻量级、高性能的服务模块,旨在帮助Min - 支持batch功能 - 提供客户端python简易接口 -## 安装部署 +## 安装 MindSpore Serving依赖MindSpore训练推理框架,安装完[MindSpore](https://gitee.com/mindspore/mindspore#%E5%AE%89%E8%A3%85) ,再安装MindSpore Serving。 -### 安装MindSpore Serving +### 安装Serving 使用pip命令安装,安装方式如下: **1、请从MindSpore Serving下载页面下载并安装whl包。** ```python -pip install mindspore_serving-1.0.0-cp37-cp37m-linux_x86_64.whl +pip install https://ms-release.obs.cn-north-4.myhuaweicloud.com/0.0.1/Serving/ascend/ubuntu_x86/mindspore_serving-0.0.1-cp37-cp37m-linux_x86_64.whl ``` **2、源码安装。** 下载[源码](https://gitee.com/mindspore/serving)。 @@ -60,104 +56,34 @@ sh build.sh -eacl # ascend 910 sh build.sh -ed ``` - 编译完后,在output/目录下找到安装包进行安装: ```python -pip install mindspore_serving-0.1.0-cp37-cp37m-linux_x86_64.whl -``` -### 配置环境变量 -Asend 910环境上安装mindspore,需要完成[环境变量配置](https://gitee.com/mindspore/docs/blob/master/install/mindspore_ascend_install_pip.md#%E9%85%8D%E7%BD%AE%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F)。 -运行MindSpore Serving,还需要增加额外mindspore软件包的安装路径下的lib路径到LD_LIBRARY_PATH。 -```shell -export LD_LIBRARY_PATH=$MINDSPORE_LIB_PATH:${LD_LIBRARY_PATH} +pip install mindspore_serving-0.0.1-cp37-cp37m-linux_x86_64.whl ``` - -### 部署MindSpore Serving -MindSpore Serving提供两种部署方式,用户可根据需要进行选择部署。 - -**轻量级部署:** -服务端调用python接口直接启动推理进程(master和worker共进程),客户端直接连接推理服务后下发推理任务。 -启动服务: +**执行以下命令,验证安装结果。导入python模块不报错即安装成功。** ```python -import os from mindspore_serving import master from mindspore_serving import worker -servable_dir = os.path.abspath(".") -worker.start_servable_in_master(servable_dir, "xxx", device_id=0) -master.start_grpc_server("127.0.0.1", 5500) ``` -**集群部署:** -服务端由master进程和worker进程组成,master用来管理集群内所有的worker节点,并进行推理任务的分发。 -启动worker: -```python -import os -from mindspore_serving import worker -servable_dir = os.path.abspath(".") -worker.start_servable(servable_dir, "lenet", device_id=0, - master_ip="127.0.0.1", master_port=5500, - host_ip="127.0.0.1", host_port=5600) -``` -启动master: -```python -from mindspore_serving import master -master.start_grpc_server("127.0.0.1", 5500) +### 配置环境变量 +Asend 910环境上安装mindspore,需要完成[环境变量配置](https://gitee.com/mindspore/docs/blob/master/install/mindspore_ascend_install_pip.md#%E9%85%8D%E7%BD%AE%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F)。 +运行MindSpore Serving,还需要增加额外mindspore软件包的安装路径下的lib路径到LD_LIBRARY_PATH。 +```shell +export LD_LIBRARY_PATH=$MINDSPORE_LIB_PATH:${LD_LIBRARY_PATH} ``` -完成服务端部署后,即可启用客户端程序执行推理操作。 ## 快速入门 -以一个简单的Add网络为例,演示MindSpore Serving如何使用。 - -### 导出模型 -使用[add_model.py](https://gitee.com/mindspore/serving/blob/master/mindspore_serving/example/add/export_model/add_model.py),构造一个只有Add算子的网络,并导出MindSpore推理部署模型。 - -```python -python add_model.py -``` -执行脚本,生成`tensor_add.mindir`文件,该模型的输入为两个shape为[2,2]的二维Tensor,输出结果是两个输入Tensor之和。 - -### 部署Serving推理服务 -执行以下[python程序](https://gitee.com/mindspore/serving/blob/master/mindspore_serving/example/add/master_with_worker.py),启动服务: -```bash -import os -from mindspore_serving import master -from mindspore_serving import worker -def start(): - servable_dir = os.path.abspath(".") - worker.start_servable_in_master(servable_dir, "add", device_id=0) - master.start_grpc_server("127.0.0.1", 5500) -``` -启动过程需要使用servable_dir路径下的模型文件和配置文件,文件目录结果如下图所示: -
add/ -├── 1 -│ └── tensor_add.mindir -└── servable_config.py --其中,模型文件为上一步网络生成的,即`tensor_add.mindir`文件。配置文件为[servable_config.py](https://gitee.com/mindspore/serving/blob/master/mindspore_serving/example/add/add/servable_config.py),其定义了模型的处理函数,包含前处理和后处理过程。 -当服务端打印日志`Serving gRPC start success, listening on 0.0.0.0:5500`时,表示Serving服务已加载推理模型完毕。 - -### 执行推理 -使用[client.py](https://gitee.com/mindspore/serving/blob/master/mindspore_serving/example/add/client.py),启动Python客户端。 -```bash -python client.py -``` - -显示如下返回值说明Serving服务已正确执行Add网络的推理。 -```bash -[{'y': array([[2. , 2.], - [2., 2.]], dtype=float32)}] -[{'y': array([[2. , 2.], - [2., 2.]], dtype=float32)}] -``` +以一个简单的[Add网络示例](docs/example.md),演示MindSpore Serving如何使用。 ## 文档 ### 开发者教程 -- [如何使用python接口开发客户端?](docs/GRPC.md) -- [如何启动Restful服务进行推理?](docs/RESTful.md) -- [如何实现模型前处理和后处理?](docs/MODEL.md) +- [gRPC接口使用说明](docs/GRPC.md) +- [RESTful接口使用说明](docs/RESTful.md) +- [模型配置接口使用说明](docs/MODEL.md) -有关安装指南、教程和API的更多详细信息,请参阅[用户文档](https://gitee.com/mindspore/serving/docs)。 +有关安装指南、教程和API的更多详细信息,请参阅[用户文档](https://gitee.com/mindspore/serving/tree/master/docs)。 ## 社区 diff --git a/docs/GRPC.md b/docs/GRPC.md index 025b3fb..a9c7a6e 100644 --- a/docs/GRPC.md +++ b/docs/GRPC.md @@ -1,4 +1,4 @@ -# gRPC接口使用 +# gRPC接口使用说明 ## 概述 MindSpore Serving提供gRPC接口访问Serving服务。在Python环境下,我们提供[mindspore_serving.client](../mindspore_serving/client/python/client.py) 接口填写请求、解析回复。接下来我们详细说明`mindspore_serving.client`如何使用。 diff --git a/docs/MODEL.md b/docs/MODEL.md index a8b1cb4..c823610 100644 --- a/docs/MODEL.md +++ b/docs/MODEL.md @@ -1,4 +1,4 @@ -# 模型配置接口 +# 模型配置接口使用说明 ## 概述 diff --git a/docs/example.md b/docs/example.md new file mode 100644 index 0000000..26b1a55 --- /dev/null +++ b/docs/example.md @@ -0,0 +1,211 @@ +# 实现一个Add网络示例 + +## 概述 +以一个简单的Add网络为例,演示MindSpore Serving如何使用。 + +### 导出模型 +使用[add_model.py](https://gitee.com/mindspore/serving/blob/master/mindspore_serving/example/add/export_model/add_model.py),构造一个只有Add算子的网络,并导出MindSpore推理部署模型。 + +```python +import os +from shutil import copyfile +import numpy as np +import mindspore.context as context +import mindspore.nn as nn +from mindspore.ops import operations as P +from mindspore import Tensor +from mindspore.train.serialization import export + +context.set_context(mode=context.GRAPH_MODE, device_target="Ascend") + +class Net(nn.Cell): + def __init__(self): + super(Net, self).__init__() + self.add = P.TensorAdd() + + def construct(self, x_, y_): + return self.add(x_, y_) + +def export_net(): + x = np.ones([2, 2]).astype(np.float32) + y = np.ones([2, 2]).astype(np.float32) + add = Net() + output = add(Tensor(x), Tensor(y)) + export(add, Tensor(x), Tensor(y), file_name='tensor_add', file_format='MINDIR') + dst_dir = '../add/1' + try: + os.mkdir(dst_dir) + except OSError: + pass + try: + dst_file = os.path.join(dst_dir, 'tensor_add.mindir') + if os.path.exists('tensor_add.mindir'): + copyfile('tensor_add.mindir', dst_file) + print("copy tensor_add.mindir to " + dst_dir + " success") + elif os.path.exists('tensor_add'): + copyfile('tensor_add', dst_file) + print("copy tensor_add to " + dst_dir + " success") + except: + print("copy tensor_add.mindir to " + dst_dir + " failed") + print(x) + print(y) + print(output.asnumpy()) + +if __name__ == "__main__": + export_net() +``` +使用MindSpore定义神经网络需要继承mindspore.nn.Cell。Cell是所有神经网络的基类。神经网络的各层需要预先在__init__方法中定义,然后通过定义construct方法来完成神经网络的前向构造。使用mindspore.train.serialization模块的export即可导出模型文件。 +更为详细完整的示例可以参考[实现一个图片分类应用](https://www.mindspore.cn/tutorial/training/zh-CN/master/quick_start/quick_start.html)。 + +执行add_model.py脚本,生成`tensor_add.mindir`文件,该模型的输入为两个shape为[2,2]的二维Tensor,输出结果是两个输入Tensor之和。 + +### 部署Serving推理服务 +启动Serving服务,当前目录下需要有模型文件夹,如add,文件夹下放置版本模型文件和配置文件,文件目录结果如下图所示: +
test_dir/ +├── add/ +│ └── servable_config.py +│ └─1/ +│ └── tensor_add.mindir +└── master_with_worker.py ++其中,模型文件为上一步网络生成的,即`tensor_add.mindir`文件,放置在文件夹1下,1为版本号,不同的版本放置在不同的文件夹下。 +配置文件为[servable_config.py](https://gitee.com/mindspore/serving/blob/master/mindspore_serving/example/add/add/servable_config.py),其定义了模型的处理函数。 +```python +from mindspore_serving.worker import register +import numpy as np + +# define preprocess pipeline, the function arg is multi instances, every instance is tuple of inputs +# this example has one input and one output +def add_trans_datatype(instances): + """preprocess python implement""" + for instance in instances: + x1 = instance[0] + x2 = instance[1] + yield x1.astype(np.float32), x2.astype(np.float32) + + +# when with_batch_dim set to False, only support 2x2 add +# when with_batch_dim set to True(default), support Nx2 add, while N is view as batch +# float32 inputs/outputs +register.declare_servable(servable_file="tensor_add.mindir", model_format="MindIR", with_batch_dim=False) + + +# register add_common method in add +@register.register_method(output_names=["y"]) +def add_common(x1, x2): # only support float32 inputs + """method add_common data flow definition, only call model servable""" + y = register.call_servable(x1, x2) + return y + + +# register add_cast method in add +@register.register_method(output_names=["y"]) +def add_cast(x1, x2): + """method add_cast data flow definition, only call preprocess and model servable""" + x1, x2 = register.call_preprocess(add_trans_datatype, x1, x2) # cast input to float32 + y = register.call_servable(x1, x2) + return y +``` +该文件定义了add_common和add_cast两个方法。 + +MindSpore Serving提供两种部署方式,轻量级部署和集群部署,用户可根据需要进行选择部署。 +**轻量级部署:** +服务端调用python接口直接启动推理进程(master和worker共进程),客户端直接连接推理服务后下发推理任务。 +执行[master_with_worker.py](https://gitee.com/mindspore/serving/blob/master/mindspore_serving/example/add/master_with_worker.py),完成轻量级部署服务如下: +```python +import os +from mindspore_serving import master +from mindspore_serving import worker + +def start(): + servable_dir = os.path.abspath(".") + worker.start_servable_in_master(servable_dir, "add", device_id=0) + master.start_grpc_server("127.0.0.1", 5500) + +if __name__ == "__main__": + start() +``` +当服务端打印日志`Serving gRPC start success, listening on 0.0.0.0:5500`时,表示Serving服务已加载推理模型完毕。 + + +**集群部署:** +服务端由master进程和worker进程组成,master用来管理集群内所有的worker节点,并进行推理任务的分发。 部署方式如下: +部署master: +```python +import os +from mindspore_serving import master + +def start(): + servable_dir = os.path.abspath(".") + master.start_grpc_server("127.0.0.1", 5500) + master.start_master_server("127.0.0.1", 6500) +if __name__ == "__main__": + start() +``` +部署worker: +```python +import os +from mindspore_serving import master + +def start(): + servable_dir = os.path.abspath(".") + worker.start_servable(servable_dir, "add", device_id=0, + master_ip="127.0.0.1", master_port=6500, + host_ip="127.0.0.1", host_port=6600) + +if __name__ == "__main__": + start() +``` +轻量级部署和集群部署除了master和woker进程是否隔离,worker使用的接口也不同,轻量级部署使用worker的start_servable_in_master接口,集群部署使用worker的start_servable接口。 + +### 执行推理 +使用[client.py](https://gitee.com/mindspore/serving/blob/master/mindspore_serving/example/add/client.py),启动Python客户端。 +```python +import numpy as np +from mindspore_serving.client import Client + +def run_add_common(): + """invoke servable add method add_common""" + client = Client("localhost", 5500, "add", "add_common") + instances = [] + + # instance 1 + x1 = np.asarray([[1, 1], [1, 1]]).astype(np.float32) + x2 = np.asarray([[1, 1], [1, 1]]).astype(np.float32) + instances.append({"x1": x1, "x2": x2}) + + # instance 2 + x1 = np.asarray([[2, 2], [2, 2]]).astype(np.float32) + x2 = np.asarray([[2, 2], [2, 2]]).astype(np.float32) + instances.append({"x1": x1, "x2": x2}) + + # instance 3 + x1 = np.asarray([[3, 3], [3, 3]]).astype(np.float32) + x2 = np.asarray([[3, 3], [3, 3]]).astype(np.float32) + instances.append({"x1": x1, "x2": x2}) + + result = client.infer(instances) + print(result) + +def run_add_cast(): + """invoke servable add method add_cast""" + client = Client("localhost", 5500, "add", "add_cast") + instances = [] + x1 = np.ones((2, 2), np.int32) + x2 = np.ones((2, 2), np.int32) + instances.append({"x1": x1, "x2": x2}) + result = client.infer(instances) + print(result) + +if __name__ == '__main__': + run_add_common() + run_add_cast() +``` + +使用mindspore_serving.client定义的Client类,分别调用模型的两个方法,显示如下返回值说明Serving服务已正确执行Add网络的推理。 +```bash +[{'y': array([[2. , 2.], + [2., 2.]], dtype=float32)}] +[{'y': array([[2. , 2.], + [2., 2.]], dtype=float32)}] +``` diff --git a/mindspore_serving/example/add/master_with_worker.py b/mindspore_serving/example/add/master_with_worker.py index 376c631..9d2a33b 100644 --- a/mindspore_serving/example/add/master_with_worker.py +++ b/mindspore_serving/example/add/master_with_worker.py @@ -22,8 +22,8 @@ def start(): servable_dir = os.path.abspath(".") worker.start_servable_in_master(servable_dir, "add", device_id=0) - master.start_grpc_server("0.0.0.0", 5500) - master.start_restful_server("0.0.0.0", 1500) + master.start_grpc_server("127.0.0.1", 5500) + master.start_restful_server("127.0.0.1", 1500) if __name__ == "__main__":