diff --git a/README.md b/README.md index eb7785801977e37853664c9ca41081cab0b537cc..81ad14c993852b1c73f44957f199d97336580388 100644 --- a/README.md +++ b/README.md @@ -16,15 +16,15 @@

-[中文](https://github.com/PaddlePaddle/Serving/blob/develop/README_CN.md) +

Motivation

-## Motivation Paddle Serving helps deep learning developers deploy an online inference service without much effort. **The goal of this project**: once you have trained a deep neural nets with [Paddle](https://github.com/PaddlePaddle/Paddle), you already have a model inference service. A demo of serving is as follows:

-## Key Features +

Key Features

+ - Integrate with Paddle training pipeline seemlessly, most paddle models can be deployed **with one line command**. - **Industrial serving features** supported, such as models management, online loading, online A/B testing etc. - **Distributed Key-Value indexing** supported that is especially useful for large scale sparse features as model inputs. @@ -32,14 +32,16 @@ Paddle Serving helps deep learning developers deploy an online inference service - **Multiple programming languages** supported on client side, such as Golang, C++ and python - **Extensible framework design** that can support model serving beyond Paddle. -## Installation +

Installation

+ +We highly recommend you to run Paddle Serving in Docker, please visit [Run in Docker](https://github.com/PaddlePaddle/Serving/blob/develop/doc/RUN_IN_DOCKER.md) ```shell pip install paddle-serving-client pip install paddle-serving-server ``` -## Quick Start Example +

Quick Start Example

### Boston House Price Prediction model ``` shell @@ -54,6 +56,17 @@ Paddle Serving provides HTTP and RPC based service for users to access ``` shell python -m paddle_serving_server.web_serve --model uci_housing_model --thread 10 --port 9292 --name uci ``` +
+ +| Argument | Type | Default | Description | +|--------------|------|-----------|--------------------------------| +| `thread` | int | `10` | Concurrency of current service | +| `port` | int | `9292` | Exposed port of current service to users| +| `name` | str | `""` | Service name, can be used to generate HTTP request url | +| `model` | str | `""` | Path of paddle model directory to be served | + +
+ ``` shell curl -H "Content-Type:application/json" -X POST -d '{"x": [0.0137, -0.1136, 0.2553, -0.0692, 0.0582, -0.0727, -0.1583, -0.0584, 0.6283, 0.4919, 0.1856, 0.0795, -0.0332], "fetch":["price"]}' http://127.0.0.1:9292/uci/prediction ``` @@ -78,47 +91,75 @@ print(fetch_map) ``` -## Models waiting for you to deploy +

Pre-built services with Paddle Serving

+

Chinese Word Segmentation

-
+- **Description**: Chinese word segmentation HTTP service that can be deployed with one line command. + +- **Download**: +``` shell +wget --no-check-certificate https://paddle-serving.bj.bcebos.com/lac/lac_model_jieba_web.tar.gz +``` +- **Host web service**: +``` shell +tar -xzf lac_model_jieba_web.tar.gz +python lac_web_service.py jieba_server_model/ lac_workdir 9292 +``` +- **Request sample**: +``` shell +curl -H "Content-Type:application/json" -X POST -d '{"words": "我爱北京天安门", "fetch":["crf_decode"]}' http://127.0.0.1:9292/lac/prediction +``` +- **Request result**: +``` shell +{"word_seg":"我|爱|北京|天安门"} +``` -| Model Name | Resnet50 | -|:--------------------: |:----------------------------------: | -| Package URL | To be released | -| Description | Get the representation of an image | -| Training Data Source | Imagenet | -
+

Chinese Sentence To Vector

+ +

Image To Vector

+ +

Image Classification

-## Document -[How to save a servable model?](doc/SAVE.md) +

Document

-[How to config Serving native operators on server side?](doc/SERVER_DAG.md) +### New to Paddle Serving +- [How to save a servable model?](doc/SAVE.md) +- [An end-to-end tutorial from training to serving](doc/END_TO_END.md) +- [Write Bert-as-Service in 10 minutes](doc/Bert_10_mins.md) -[How to develop a new Serving operator](doc/NEW_OPERATOR.md) +### Developers +- [How to config Serving native operators on server side?](doc/SERVER_DAG.md) +- [How to develop a new Serving operator](doc/NEW_OPERATOR.md) +- [Golang client](doc/IMDB_GO_CLIENT.md) +- [Compile from source code(Chinese)](doc/COMPILE.md) -[Golang client](doc/IMDB_GO_CLIENT.md) +### About Efficiency +- [How profile serving efficiency?(Chinese)](https://github.com/PaddlePaddle/Serving/tree/develop/python/examples/util) -[Compile from source code(Chinese)](doc/COMPILE.md) +### FAQ +- [FAQ(Chinese)](doc/FAQ.md) -[How profile serving efficiency?(Chinese)](https://github.com/PaddlePaddle/Serving/tree/develop/python/examples/util) +### Design +- [Design Doc(Chinese)](doc/DESIGN.md) -[FAQ(Chinese)](doc/FAQ.md) +

Community

-[Design Doc(Chinese)](doc/DESIGN.md) +### Slack -## Join Community To connect with other users and contributors, welcome to join our [Slack channel](https://paddleserving.slack.com/archives/CUBPKHKMJ) -## Contribution +### Contribution If you want to contribute code to Paddle Serving, please reference [Contribution Guidelines](doc/CONTRIBUTE.md) ### Feedback + For any feedback or to report a bug, please propose a [GitHub Issue](https://github.com/PaddlePaddle/Serving/issues). -## License +### License + [Apache 2.0 License](https://github.com/PaddlePaddle/Serving/blob/develop/LICENSE) diff --git a/README_CN.md b/README_CN.md index 995b6d0c66a39eae8302209f538ae43385f673f8..8400038f840a9f26a1342d9fcf4bd9729adcb06c 100644 --- a/README_CN.md +++ b/README_CN.md @@ -22,6 +22,8 @@ Paddle Serving 帮助深度学习开发者轻易部署在线预测服务。 ** ## 安装 +强烈建议您在Docker内构建Paddle Serving,请查看[如何在Docker中运行PaddleServing](doc/RUN_IN_DOCKER_CN.md) + ```shell pip install paddle-serving-client pip install paddle-serving-server diff --git a/doc/README_CN.md b/doc/README_CN.md index 7bdcbe40280c954187e3ff619b4f7cf8e6f47a7d..f8d42e6f1e72f1ac34939e5795df3e6604924bad 100644 --- a/doc/README_CN.md +++ b/doc/README_CN.md @@ -9,6 +9,9 @@ Paddle Serving是PaddlePaddle的在线预估服务框架,能够帮助开发者 Paddle Serving当前的develop版本支持轻量级Python API进行快速预测,并且与Paddle的训练可以打通。我们以最经典的波士顿房价预测为示例,完整说明在单机进行模型训练以及使用Paddle Serving进行模型部署的过程。 #### 安装 + +强烈建议您在Docker内构建Paddle Serving,请查看[如何在Docker中运行PaddleServing](doc/RUN_IN_DOCKER_CN.md) + ``` pip install paddle-serving-client pip install paddle-serving-server diff --git a/doc/RUN_IN_DOCKER.md b/doc/RUN_IN_DOCKER.md new file mode 100644 index 0000000000000000000000000000000000000000..345aabed52cb30282057ea7f5ba4953a9681d6d8 --- /dev/null +++ b/doc/RUN_IN_DOCKER.md @@ -0,0 +1,175 @@ +# How to run PaddleServing in Docker + +## Requirements + +Docker (GPU version requires nvidia-docker to be installed on the GPU machine) + +## CPU + +### Get docker image + +You can get images in two ways: + +1. Pull image directly + + ```bash + docker pull hub.baidubce.com/ctr/paddleserving:0.1.3 + ``` + +2. Building image based on dockerfile + + Create a new folder and copy [Dockerfile](../tools/Dockerfile) to this folder, and run the following command: + + ```bash + docker build -t hub.baidubce.com/ctr/paddleserving:0.1.3 . + ``` + +### Create container + +```bash +docker run -p 9292:9292 --name test -dit hub.baidubce.com/ctr/paddleserving:0.1.3 +docker exec -it test bash +``` + +The `-p` option is to map the `9292` port of the container to the `9292` port of the host. + +### Install PaddleServing + +In order to make the image smaller, the PaddleServing package is not installed in the image. You can run the following command to install it + +```bash +pip install paddle-serving-server +``` + +### Test example + +Get the trained Boston house price prediction model by the following command: + +```bash +wget --no-check-certificate https://paddle-serving.bj.bcebos.com/uci_housing.tar.gz +tar -xzf uci_housing.tar.gz +``` + +- Test HTTP service + + Running on the Server side (inside the container): + + ```bash + python -m paddle_serving_server.web_serve --model uci_housing_model --thread 10 --port 9292 --name uci &>std.log 2>err.log & + ``` + + Running on the Client side (inside or outside the container): + + ```bash + curl -H "Content-Type:application/json" -X POST -d '{"x": [0.0137, -0.1136, 0.2553, -0.0692, 0.0582, -0.0727, -0.1583, -0.0584, 0.6283, 0.4919, 0.1856, 0.0795, -0.0332], "fetch":["price"]}' http://127.0.0.1:9292/uci/prediction + ``` + +- Test RPC service + + Running on the Server side (inside the container): + + ```bash + python -m paddle_serving_server.serve --model uci_housing_model --thread 10 --port 9292 &>std.log 2>err.log & + ``` + + Running following Python code on the Client side (inside or outside the container, The `paddle-serving-client` package needs to be installed): + + ```bash + from paddle_serving_client import Client + + client = Client() + client.load_client_config("uci_housing_client/serving_client_conf.prototxt") + client.connect(["127.0.0.1:9292"]) + data = [0.0137, -0.1136, 0.2553, -0.0692, 0.0582, -0.0727, + -0.1583, -0.0584, 0.6283, 0.4919, 0.1856, 0.0795, -0.0332] + fetch_map = client.predict(feed={"x": data}, fetch=["price"]) + print(fetch_map) + ``` + + + +## GPU + +The GPU version is basically the same as the CPU version, with only some differences in interface naming (GPU version requires nvidia-docker to be installed on the GPU machine). + +### Get docker image + +You can also get images in two ways: + +1. Pull image directly + + ```bash + nvidia-docker pull hub.baidubce.com/ctr/paddleserving:0.1.3-gpu + ``` + +2. Building image based on dockerfile + + Create a new folder and copy [Dockerfile.gpu](../tools/Dockerfile.gpu) to this folder, and run the following command: + + ```bash + nvidia-docker build -t hub.baidubce.com/ctr/paddleserving:0.1.3-gpu . + ``` + +### Create container + +```bash +nvidia-docker run -p 9292:9292 --name test -dit hub.baidubce.com/ctr/paddleserving:0.1.3-gpu +nvidia-docker exec -it test bash +``` + +The `-p` option is to map the `9292` port of the container to the `9292` port of the host. + +### Install PaddleServing + +In order to make the image smaller, the PaddleServing package is not installed in the image. You can run the following command to install it: + +```bash +pip install paddle-serving-server-gpu +``` + +### Test example + +Get the trained Boston house price prediction model by the following command: + +```bash +wget --no-check-certificate https://paddle-serving.bj.bcebos.com/uci_housing.tar.gz +tar -xzf uci_housing.tar.gz +``` + +- Test HTTP service + + Running on the Server side (inside the container): + + ```bash + python -m paddle_serving_server_gpu.web_serve --model uci_housing_model --thread 10 --port 9292 --name uci + ``` + + Running on the Client side (inside or outside the container): + + ```bash + curl -H "Content-Type:application/json" -X POST -d '{"x": [0.0137, -0.1136, 0.2553, -0.0692, 0.0582, -0.0727, -0.1583, -0.0584, 0.6283, 0.4919, 0.1856, 0.0795, -0.0332], "fetch":["price"]}' http://127.0.0.1:9292/uci/prediction + ``` + +- Test RPC service + + Running on the Server side (inside the container): + + ```bash + python -m paddle_serving_server_gpu.serve --model uci_housing_model --thread 10 --port 9292 + ``` + + Running following Python code on the Client side (inside or outside the container, The `paddle-serving-client` package needs to be installed): + + ```bash + from paddle_serving_client import Client + + client = Client() + client.load_client_config("uci_housing_client/serving_client_conf.prototxt") + client.connect(["127.0.0.1:9292"]) + data = [0.0137, -0.1136, 0.2553, -0.0692, 0.0582, -0.0727, + -0.1583, -0.0584, 0.6283, 0.4919, 0.1856, 0.0795, -0.0332] + fetch_map = client.predict(feed={"x": data}, fetch=["price"]) + print(fetch_map) + ``` + + diff --git a/doc/RUN_IN_DOCKER_CN.md b/doc/RUN_IN_DOCKER_CN.md new file mode 100644 index 0000000000000000000000000000000000000000..7e2f28bdbd73c793faee96def6b625e1bbff2ba9 --- /dev/null +++ b/doc/RUN_IN_DOCKER_CN.md @@ -0,0 +1,171 @@ +# 如何在Docker中运行PaddleServing + +## 环境要求 + +Docker(GPU版本需要在GPU机器上安装nvidia-docker) + +## CPU版本 + +### 获取镜像 + +可以通过两种方式获取镜像。 + +1. 直接拉取镜像 + + ```bash + docker pull hub.baidubce.com/ctr/paddleserving:0.1.3 + ``` + +2. 基于Dockerfile构建镜像 + + 建立新目录,复制[Dockerfile](../tools/Dockerfile)内容到该目录下Dockerfile文件。执行 + + ```bash + docker build -t hub.baidubce.com/ctr/paddleserving:0.1.3 . + ``` + +### 创建容器并进入 + +```bash +docker run -p 9292:9292 --name test -dit hub.baidubce.com/ctr/paddleserving:0.1.3 +docker exec -it test bash +``` + +`-p`选项是为了将容器的`9292`端口映射到宿主机的`9292`端口。 + +### 安装PaddleServing + +为了减小镜像的体积,镜像中没有安装Serving包,要执行下面命令进行安装 + +```bash +pip install paddle-serving-server +``` + +### 测试example + +通过下面命令获取训练好的Boston房价预估模型: + +```bash +wget --no-check-certificate https://paddle-serving.bj.bcebos.com/uci_housing.tar.gz +tar -xzf uci_housing.tar.gz +``` + +- 测试HTTP服务 + + 在Server端(容器内)运行: + + ```bash + python -m paddle_serving_server.web_serve --model uci_housing_model --thread 10 --port 9292 --name uci &>std.log 2>err.log & + ``` + + 在Client端(容器内或容器外)运行: + + ```bash + curl -H "Content-Type:application/json" -X POST -d '{"x": [0.0137, -0.1136, 0.2553, -0.0692, 0.0582, -0.0727, -0.1583, -0.0584, 0.6283, 0.4919, 0.1856, 0.0795, -0.0332], "fetch":["price"]}' http://127.0.0.1:9292/uci/prediction + ``` + +- 测试RPC服务 + + 在Server端(容器内)运行: + + ```bash + python -m paddle_serving_server.serve --model uci_housing_model --thread 10 --port 9292 &>std.log 2>err.log & + ``` + + 在Client端(容器内或容器外,需要安装`paddle-serving-client`包)运行下面Python代码: + + ```python + from paddle_serving_client import Client + + client = Client() + client.load_client_config("uci_housing_client/serving_client_conf.prototxt") + client.connect(["127.0.0.1:9292"]) + data = [0.0137, -0.1136, 0.2553, -0.0692, 0.0582, -0.0727, + -0.1583, -0.0584, 0.6283, 0.4919, 0.1856, 0.0795, -0.0332] + fetch_map = client.predict(feed={"x": data}, fetch=["price"]) + print(fetch_map) + ``` + +## GPU版本 + +GPU版本与CPU版本基本一致,只有部分接口命名的差别(GPU版本需要在GPU机器上安装nvidia-docker)。 + +### 获取镜像 + +可以通过两种方式获取镜像。 + +1. 直接拉取镜像 + + ```bash + nvidia-docker pull hub.baidubce.com/ctr/paddleserving:0.1.3-gpu + ``` + +2. 基于Dockerfile构建镜像 + + 建立新目录,复制[Dockerfile.gpu](../tools/Dockerfile.gpu)内容到该目录下Dockerfile文件。执行 + + ```bash + nvidia-docker build -t hub.baidubce.com/ctr/paddleserving:0.1.3-gpu . + ``` + +### 创建容器并进入 + +```bash +nvidia-docker run -p 9292:9292 --name test -dit hub.baidubce.com/ctr/paddleserving:0.1.3-gpu +nvidia-docker exec -it test bash +``` + +`-p`选项是为了将容器的`9292`端口映射到宿主机的`9292`端口。 + +### 安装PaddleServing + +为了减小镜像的体积,镜像中没有安装Serving包,要执行下面命令进行安装 + +```bash +pip install paddle-serving-server-gpu +``` + +### 测试example + +通过下面命令获取训练好的Boston房价预估模型: + +```bash +wget --no-check-certificate https://paddle-serving.bj.bcebos.com/uci_housing.tar.gz +tar -xzf uci_housing.tar.gz +``` + +- 测试HTTP服务 + + 在Server端(容器内)运行: + + ```bash + python -m paddle_serving_server_gpu.web_serve --model uci_housing_model --thread 10 --port 9292 --name uci + ``` + + 在Client端(容器内或容器外)运行: + + ```bash + curl -H "Content-Type:application/json" -X POST -d '{"x": [0.0137, -0.1136, 0.2553, -0.0692, 0.0582, -0.0727, -0.1583, -0.0584, 0.6283, 0.4919, 0.1856, 0.0795, -0.0332], "fetch":["price"]}' http://127.0.0.1:9292/uci/prediction + ``` + +- 测试RPC服务 + + 在Server端(容器内)运行: + + ```bash + python -m paddle_serving_server_gpu.serve --model uci_housing_model --thread 10 --port 9292 + ``` + + 在Client端(容器内或容器外,需要安装`paddle-serving-client`包)运行下面Python代码: + + ```bash + from paddle_serving_client import Client + + client = Client() + client.load_client_config("uci_housing_client/serving_client_conf.prototxt") + client.connect(["127.0.0.1:9292"]) + data = [0.0137, -0.1136, 0.2553, -0.0692, 0.0582, -0.0727, + -0.1583, -0.0584, 0.6283, 0.4919, 0.1856, 0.0795, -0.0332] + fetch_map = client.predict(feed={"x": data}, fetch=["price"]) + print(fetch_map) + ``` diff --git a/doc/demo.gif b/doc/demo.gif index 1fd6b40024aacff3c97bb0607454156d3a8d0649..8d1accfc405686cf49891a8c97fe75f52e3daf12 100644 Binary files a/doc/demo.gif and b/doc/demo.gif differ diff --git a/python/examples/imagenet/image_classification_service_gpu.py b/python/examples/imagenet/image_classification_service_gpu.py index 8fc92d918867142c6c442cb9eba61e2a9fb1f0e5..8a0bea938638c57a609a604181420929c4a9ca59 100644 --- a/python/examples/imagenet/image_classification_service_gpu.py +++ b/python/examples/imagenet/image_classification_service_gpu.py @@ -14,16 +14,13 @@ from paddle_serving_server_gpu.web_service import WebService import sys -import os +import cv2 import base64 +import numpy as np from image_reader import ImageReader class ImageService(WebService): - """ - preprocessing function for image classification - """ - def preprocess(self, feed={}, fetch=[]): reader = ImageReader() if "image" not in feed: @@ -37,9 +34,7 @@ class ImageService(WebService): image_service = ImageService(name="image") image_service.load_model_config(sys.argv[1]) -gpu_ids = os.environ["CUDA_VISIBLE_DEVICES"] -gpus = [int(x) for x in gpu_ids.split(",")] -image_service.set_gpus(gpus) +image_service.set_gpus("0,1,2,3") image_service.prepare_server( workdir=sys.argv[2], port=int(sys.argv[3]), device="gpu") image_service.run_server() diff --git a/python/examples/imagenet/image_http_client.py b/python/examples/imagenet/image_http_client.py index f8b15dafc73ffac1e121610204ffe3cce23748a3..b61f0dd7d8d5ed25ecc828b5d0882ba11a116019 100644 --- a/python/examples/imagenet/image_http_client.py +++ b/python/examples/imagenet/image_http_client.py @@ -16,6 +16,7 @@ import requests import base64 import json import time +import os def predict(image_path, server): @@ -23,13 +24,17 @@ def predict(image_path, server): req = json.dumps({"image": image, "fetch": ["score"]}) r = requests.post( server, data=req, headers={"Content-Type": "application/json"}) + return r if __name__ == "__main__": - server = "http://127.0.0.1:9393/image/prediction" - image_path = "./data/n01440764_10026.JPEG" + server = "http://127.0.0.1:9295/image/prediction" + #image_path = "./data/n01440764_10026.JPEG" + image_list = os.listdir("./data/image_data/n01440764/") start = time.time() - for i in range(1000): - predict(image_path, server) + for img in image_list: + image_file = "./data/image_data/n01440764/" + img + res = predict(image_file, server) + print(res.json()["score"][0]) end = time.time() print(end - start) diff --git a/python/examples/lac/benchmark.py b/python/examples/lac/benchmark.py new file mode 100644 index 0000000000000000000000000000000000000000..53d0881ed74e5e19104a70fb93d6872141d27afd --- /dev/null +++ b/python/examples/lac/benchmark.py @@ -0,0 +1,53 @@ +# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# pylint: disable=doc-string-missing + +import sys +import time +import requests +from lac_reader import LACReader +from paddle_serving_client import Client +from paddle_serving_client.utils import MultiThreadRunner +from paddle_serving_client.utils import benchmark_args + +args = benchmark_args() + + +def single_func(idx, resource): + reader = LACReader("lac_dict") + start = time.time() + if args.request == "rpc": + client = Client() + client.load_client_config(args.model) + client.connect([args.endpoint]) + fin = open("jieba_test.txt") + for line in fin: + feed_data = reader.process(line) + fetch_map = client.predict( + feed={"words": feed_data}, fetch=["crf_decode"]) + elif args.request == "http": + fin = open("jieba_test.txt") + for line in fin: + req_data = {"words": line.strip(), "fetch": ["crf_decode"]} + r = requests.post( + "http://{}/lac/prediction".format(args.endpoint), + data={"words": line.strip(), + "fetch": ["crf_decode"]}) + end = time.time() + return [[end - start]] + + +multi_thread_runner = MultiThreadRunner() +result = multi_thread_runner.run(single_func, args.thread, {}) +print(result) diff --git a/python/examples/lac/get_data.sh b/python/examples/lac/get_data.sh new file mode 100644 index 0000000000000000000000000000000000000000..6b72850d35b7a7b5e43b34d31c7a903e05f07440 --- /dev/null +++ b/python/examples/lac/get_data.sh @@ -0,0 +1,2 @@ +wget --no-check-certificate https://paddle-serving.bj.bcebos.com/lac/lac_model.tar.gz +tar -zxvf lac_model.tar.gz diff --git a/python/examples/lac/lac_client.py b/python/examples/lac/lac_client.py new file mode 100644 index 0000000000000000000000000000000000000000..f2a8e858ed72ac4043a2bb3162a39a2aff233043 --- /dev/null +++ b/python/examples/lac/lac_client.py @@ -0,0 +1,35 @@ +# encoding=utf-8 +# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# pylint: disable=doc-string-missing + +from paddle_serving_client import Client +from lac_reader import LACReader +import sys +import os +import io + +client = Client() +client.load_client_config(sys.argv[1]) +client.connect(["127.0.0.1:9280"]) + +reader = LACReader(sys.argv[2]) +for line in sys.stdin: + if len(line) <= 0: + continue + feed_data = reader.process(line) + if len(feed_data) <= 0: + continue + fetch_map = client.predict(feed={"words": feed_data}, fetch=["crf_decode"]) + print(fetch_map) diff --git a/python/examples/lac/lac_http_client.py b/python/examples/lac/lac_http_client.py new file mode 100644 index 0000000000000000000000000000000000000000..852d785f368e95bb16bfd5804e3153b022945f59 --- /dev/null +++ b/python/examples/lac/lac_http_client.py @@ -0,0 +1,27 @@ +# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#coding=utf-8 +import requests +import json +import time + +if __name__ == "__main__": + server = "http://127.0.0.1:9280/lac/prediction" + fin = open("jieba_test.txt", "r") + start = time.time() + for line in fin: + req_data = {"words": line.strip(), "fetch": ["crf_decode"]} + r = requests.post(server, json=req_data) + end = time.time() + print(end - start) diff --git a/python/examples/lac/lac_reader.py b/python/examples/lac/lac_reader.py new file mode 100644 index 0000000000000000000000000000000000000000..087ec8bb9e1a44afa2ba5a1cc9931e350aa76fb7 --- /dev/null +++ b/python/examples/lac/lac_reader.py @@ -0,0 +1,101 @@ +# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from paddle_serving_client import Client +import sys +reload(sys) +sys.setdefaultencoding('utf-8') +import os +import io + + +def load_kv_dict(dict_path, + reverse=False, + delimiter="\t", + key_func=None, + value_func=None): + result_dict = {} + for line in io.open(dict_path, "r", encoding="utf8"): + terms = line.strip("\n").split(delimiter) + if len(terms) != 2: + continue + if reverse: + value, key = terms + else: + key, value = terms + if key in result_dict: + raise KeyError("key duplicated with [%s]" % (key)) + if key_func: + key = key_func(key) + if value_func: + value = value_func(value) + result_dict[key] = value + return result_dict + + +class LACReader(object): + """data reader""" + + def __init__(self, dict_folder): + # read dict + #basepath = os.path.abspath(__file__) + #folder = os.path.dirname(basepath) + word_dict_path = os.path.join(dict_folder, "word.dic") + label_dict_path = os.path.join(dict_folder, "tag.dic") + self.word2id_dict = load_kv_dict( + word_dict_path, reverse=True, value_func=int) + self.id2word_dict = load_kv_dict(word_dict_path) + self.label2id_dict = load_kv_dict( + label_dict_path, reverse=True, value_func=int) + self.id2label_dict = load_kv_dict(label_dict_path) + + @property + def vocab_size(self): + """vocabulary size""" + return max(self.word2id_dict.values()) + 1 + + @property + def num_labels(self): + """num_labels""" + return max(self.label2id_dict.values()) + 1 + + def word_to_ids(self, words): + """convert word to word index""" + word_ids = [] + idx = 0 + try: + words = unicode(words, 'utf-8') + except: + pass + for word in words: + if word not in self.word2id_dict: + word = "OOV" + word_id = self.word2id_dict[word] + word_ids.append(word_id) + return word_ids + + def label_to_ids(self, labels): + """convert label to label index""" + label_ids = [] + for label in labels: + if label not in self.label2id_dict: + label = "O" + label_id = self.label2id_dict[label] + label_ids.append(label_id) + return label_ids + + def process(self, sent): + words = sent.strip() + word_ids = self.word_to_ids(words) + return word_ids diff --git a/python/examples/lac/lac_web_service.py b/python/examples/lac/lac_web_service.py new file mode 100644 index 0000000000000000000000000000000000000000..4a58c6a43caea4045220546488226da121bfdc17 --- /dev/null +++ b/python/examples/lac/lac_web_service.py @@ -0,0 +1,36 @@ +# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from paddle_serving_server.web_service import WebService +import sys +from lac_reader import LACReader + + +class LACService(WebService): + def load_reader(self): + self.reader = LACReader("lac_dict") + + def preprocess(self, feed={}, fetch=[]): + if "words" not in feed: + raise ("feed data error!") + feed_data = self.reader.process(feed["words"]) + return {"words": feed_data}, fetch + + +lac_service = LACService(name="lac") +lac_service.load_model_config(sys.argv[1]) +lac_service.load_reader() +lac_service.prepare_server( + workdir=sys.argv[2], port=int(sys.argv[3]), device="cpu") +lac_service.run_server() diff --git a/python/examples/lac/utils.py b/python/examples/lac/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..64602902f362cc847c705a3e18d3e76255961314 --- /dev/null +++ b/python/examples/lac/utils.py @@ -0,0 +1,141 @@ +# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" +util tools +""" +from __future__ import print_function +import os +import sys +import numpy as np +import paddle.fluid as fluid +import io + + +def str2bool(v): + """ + argparse does not support True or False in python + """ + return v.lower() in ("true", "t", "1") + + +def parse_result(words, crf_decode, dataset): + """ parse result """ + offset_list = (crf_decode.lod())[0] + words = np.array(words) + crf_decode = np.array(crf_decode) + batch_size = len(offset_list) - 1 + + for sent_index in range(batch_size): + begin, end = offset_list[sent_index], offset_list[sent_index + 1] + sent = [] + for id in words[begin:end]: + if dataset.id2word_dict[str(id[0])] == 'OOV': + sent.append(' ') + else: + sent.append(dataset.id2word_dict[str(id[0])]) + tags = [ + dataset.id2label_dict[str(id[0])] for id in crf_decode[begin:end] + ] + + sent_out = [] + tags_out = [] + parital_word = "" + for ind, tag in enumerate(tags): + # for the first word + if parital_word == "": + parital_word = sent[ind] + tags_out.append(tag.split('-')[0]) + continue + + # for the beginning of word + if tag.endswith("-B") or (tag == "O" and tags[ind - 1] != "O"): + sent_out.append(parital_word) + tags_out.append(tag.split('-')[0]) + parital_word = sent[ind] + continue + + parital_word += sent[ind] + + # append the last word, except for len(tags)=0 + if len(sent_out) < len(tags_out): + sent_out.append(parital_word) + return sent_out, tags_out + + +def parse_padding_result(words, crf_decode, seq_lens, dataset): + """ parse padding result """ + words = np.squeeze(words) + batch_size = len(seq_lens) + + batch_out = [] + for sent_index in range(batch_size): + + sent = [] + for id in words[begin:end]: + if dataset.id2word_dict[str(id[0])] == 'OOV': + sent.append(' ') + else: + sent.append(dataset.id2word_dict[str(id[0])]) + tags = [ + dataset.id2label_dict[str(id)] + for id in crf_decode[sent_index][1:seq_lens[sent_index] - 1] + ] + + sent_out = [] + tags_out = [] + parital_word = "" + for ind, tag in enumerate(tags): + # for the first word + if parital_word == "": + parital_word = sent[ind] + tags_out.append(tag.split('-')[0]) + continue + + # for the beginning of word + if tag.endswith("-B") or (tag == "O" and tags[ind - 1] != "O"): + sent_out.append(parital_word) + tags_out.append(tag.split('-')[0]) + parital_word = sent[ind] + continue + + parital_word += sent[ind] + + # append the last word, except for len(tags)=0 + if len(sent_out) < len(tags_out): + sent_out.append(parital_word) + + batch_out.append([sent_out, tags_out]) + return batch_out + + +def init_checkpoint(exe, init_checkpoint_path, main_program): + """ + Init CheckPoint + """ + assert os.path.exists( + init_checkpoint_path), "[%s] cann't be found." % init_checkpoint_path + + def existed_persitables(var): + """ + If existed presitabels + """ + if not fluid.io.is_persistable(var): + return False + return os.path.exists(os.path.join(init_checkpoint_path, var.name)) + + fluid.io.load_vars( + exe, + init_checkpoint_path, + main_program=main_program, + predicate=existed_persitables) diff --git a/python/paddle_serving_server/serve.py b/python/paddle_serving_server/serve.py index c86c3f46b3b3ef83fb5fe630031cf28a95c52649..279e3a895e975473fc5569c4716368c3dda1d9f1 100644 --- a/python/paddle_serving_server/serve.py +++ b/python/paddle_serving_server/serve.py @@ -18,6 +18,7 @@ Usage: python -m paddle_serving_server.serve --model ./serving_server_model --port 9292 """ import argparse +from .web_service import WebService def parse_args(): # pylint: disable=doc-string-missing @@ -28,6 +29,8 @@ def parse_args(): # pylint: disable=doc-string-missing "--model", type=str, default="", help="Model for serving") parser.add_argument( "--port", type=int, default=9292, help="Port the server") + parser.add_argument( + "--name", type=str, default="None", help="Web service name") parser.add_argument( "--workdir", type=str, @@ -71,4 +74,13 @@ def start_standard_model(): # pylint: disable=doc-string-missing if __name__ == "__main__": - start_standard_model() + + args = parse_args() + if args.name == "None": + start_standard_model() + else: + service = WebService(name=args.name) + service.load_model_config(args.model) + service.prepare_server( + workdir=args.workdir, port=args.port, device=args.device) + service.run_server() diff --git a/python/paddle_serving_server/web_serve.py b/python/paddle_serving_server/web_serve.py deleted file mode 100644 index 46437ad5e53288c6ab03b32ea8882e1b3cfa66a3..0000000000000000000000000000000000000000 --- a/python/paddle_serving_server/web_serve.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -Usage: - Host a trained paddle model with one line command - Example: - python -m paddle_serving_server.web_serve --model ./serving_server_model --port 9292 -""" -import argparse -from multiprocessing import Pool, Process -from .web_service import WebService - - -def parse_args(): # pylint: disable=doc-string-missing - parser = argparse.ArgumentParser("web_serve") - parser.add_argument( - "--thread", type=int, default=10, help="Concurrency of server") - parser.add_argument( - "--model", type=str, default="", help="Model for serving") - parser.add_argument( - "--port", type=int, default=9292, help="Port the server") - parser.add_argument( - "--workdir", - type=str, - default="workdir", - help="Working dir of current service") - parser.add_argument( - "--device", type=str, default="cpu", help="Type of device") - parser.add_argument( - "--name", type=str, default="default", help="Default service name") - return parser.parse_args() - - -if __name__ == "__main__": - args = parse_args() - service = WebService(name=args.name) - service.load_model_config(args.model) - service.prepare_server( - workdir=args.workdir, port=args.port, device=args.device) - service.run_server() diff --git a/python/paddle_serving_server_gpu/__init__.py b/python/paddle_serving_server_gpu/__init__.py index 8ee1e137fb8fe282d26bda95e4b4bffa6f670f11..02b55801c35fb5d1ed7e35c249ac07e4d3eb45ab 100644 --- a/python/paddle_serving_server_gpu/__init__.py +++ b/python/paddle_serving_server_gpu/__init__.py @@ -42,7 +42,7 @@ def serve_args(): "--device", type=str, default="gpu", help="Type of device") parser.add_argument("--gpu_ids", type=str, default="", help="gpu ids") parser.add_argument( - "--name", type=str, default="default", help="Default service name") + "--name", type=str, default="None", help="Default service name") return parser.parse_args() diff --git a/python/paddle_serving_server_gpu/serve.py b/python/paddle_serving_server_gpu/serve.py index b12034667867f6ccbfe88668e37b9512f048bd63..882e6a270ff26eada6d94ce9c0c81b0ef3b7a3d8 100644 --- a/python/paddle_serving_server_gpu/serve.py +++ b/python/paddle_serving_server_gpu/serve.py @@ -89,4 +89,18 @@ def start_multi_card(args): # pylint: disable=doc-string-missing if __name__ == "__main__": args = serve_args() - start_multi_card(args) + if args.name == "None": + start_multi_card(args) + else: + web_service = WebService(name=args.name) + web_service.load_model_config(args.model) + gpu_ids = [] + if args.gpu_ids == "": + if "CUDA_VISIBLE_DEVICES" in os.environ: + gpu_ids = os.environ["CUDA_VISIBLE_DEVICES"] + if len(gpu_ids) > 0: + gpus = [int(x) for x in gpu_ids.split(",")] + web_service.set_gpus(gpus) + web_service.prepare_server( + workdir=args.workdir, port=args.port, device=args.device) + web_service.run_server() diff --git a/python/paddle_serving_server_gpu/web_serve.py b/python/paddle_serving_server_gpu/web_serve.py deleted file mode 100644 index 734e6d7b93b4f3ad22f330b1545b63c6ac6f2838..0000000000000000000000000000000000000000 --- a/python/paddle_serving_server_gpu/web_serve.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -""" -Usage: - Host a trained paddle model with one line command - Example: - python -m paddle_serving_server.web_serve --model ./serving_server_model --port 9292 -""" -import os -from multiprocessing import Pool, Process -from .web_service import WebService -import paddle_serving_server_gpu as serving -from paddle_serving_server_gpu import serve_args - -if __name__ == "__main__": - args = serve_args() - web_service = WebService(name=args.name) - web_service.load_model_config(args.model) - gpu_ids = [] - if args.gpu_ids == "": - if "CUDA_VISIBLE_DEVICES" in os.environ: - gpu_ids = os.environ["CUDA_VISIBLE_DEVICES"] - if len(gpu_ids) > 0: - gpus = [int(x) for x in gpu_ids.split(",")] - web_service.set_gpus(gpus) - web_service.prepare_server( - workdir=args.workdir, port=args.port, device=args.device) - web_service.run_server() diff --git a/python/paddle_serving_server_gpu/web_service.py b/python/paddle_serving_server_gpu/web_service.py index fbb52470d48f45795c6e910600a1368d4bf3d8d2..4d88994cc6094488aaf71ff3e37a74acc93579c4 100755 --- a/python/paddle_serving_server_gpu/web_service.py +++ b/python/paddle_serving_server_gpu/web_service.py @@ -15,7 +15,7 @@ # pylint: disable=doc-string-missing from flask import Flask, request, abort -from multiprocessing import Pool, Process +from multiprocessing import Pool, Process, Queue from paddle_serving_server_gpu import OpMaker, OpSeqMaker, Server import paddle_serving_server_gpu as serving from paddle_serving_client import Client @@ -29,12 +29,13 @@ class WebService(object): self.name = name self.gpus = [] self.rpc_service_list = [] + self.input_queues = [] def load_model_config(self, model_config): self.model_config = model_config def set_gpus(self, gpus): - self.gpus = gpus + self.gpus = [int(x) for x in gpus.split(",")] def default_rpc_service(self, workdir="conf", @@ -86,60 +87,101 @@ class WebService(object): gpuid, thread_num=10)) + def producers(self, inputqueue, endpoint): + client = Client() + client.load_client_config("{}/serving_server_conf.prototxt".format( + self.model_config)) + client.connect([endpoint]) + while True: + request_json = inputqueue.get() + feed, fetch = self.preprocess(request_json, request_json["fetch"]) + if "fetch" in feed: + del feed["fetch"] + fetch_map = client.predict(feed=feed, fetch=fetch) + fetch_map = self.postprocess( + feed=request_json, fetch=fetch, fetch_map=fetch_map) + self.output_queue.put(fetch_map) + def _launch_web_service(self, gpu_num): app_instance = Flask(__name__) - client_list = [] - if gpu_num > 1: - gpu_num = 0 - for i in range(gpu_num): - client_service = Client() - client_service.load_client_config( - "{}/serving_server_conf.prototxt".format(self.model_config)) - client_service.connect(["0.0.0.0:{}".format(self.port + i + 1)]) - client_list.append(client_service) - time.sleep(1) service_name = "/" + self.name + "/prediction" + self.input_queues = [] + self.output_queue = Queue() + for i in range(gpu_num): + self.input_queues.append(Queue()) + + producer_list = [] + for i, input_q in enumerate(self.input_queues): + producer_processes = Process( + target=self.producers, + args=( + input_q, + "0.0.0.0:{}".format(self.port + 1 + i), )) + producer_list.append(producer_processes) + + for p in producer_list: + p.start() + + client = Client() + client.load_client_config("{}/serving_server_conf.prototxt".format( + self.model_config)) + client.connect(["0.0.0.0:{}".format(self.port + 1)]) + + self.idx = 0 + @app_instance.route(service_name, methods=['POST']) def get_prediction(): if not request.json: abort(400) if "fetch" not in request.json: abort(400) + + self.input_queues[self.idx].put(request.json) + + #self.input_queues[0].put(request.json) + self.idx += 1 + if self.idx >= len(self.gpus): + self.idx = 0 + result = self.output_queue.get() + return result + ''' feed, fetch = self.preprocess(request.json, request.json["fetch"]) if "fetch" in feed: del feed["fetch"] - fetch_map = client_list[0].predict(feed=feed, fetch=fetch) + fetch_map = client.predict(feed=feed, fetch=fetch) fetch_map = self.postprocess( feed=request.json, fetch=fetch, fetch_map=fetch_map) return fetch_map + ''' app_instance.run(host="0.0.0.0", port=self.port, threaded=False, processes=1) + for p in producer_list: + p.join() + def run_server(self): import socket localIP = socket.gethostbyname(socket.gethostname()) print("web service address:") print("http://{}:{}/{}/prediction".format(localIP, self.port, self.name)) - - rpc_processes = [] - for idx in range(len(self.rpc_service_list)): - p_rpc = Process(target=self._launch_rpc_service, args=(idx, )) - rpc_processes.append(p_rpc) - - for p in rpc_processes: + server_pros = [] + for i, service in enumerate(self.rpc_service_list): + p = Process(target=self._launch_rpc_service, args=(i, )) + server_pros.append(p) + for p in server_pros: p.start() p_web = Process( target=self._launch_web_service, args=(len(self.gpus), )) p_web.start() - for p in rpc_processes: - p.join() p_web.join() + for p in server_pros: + p.join() def preprocess(self, feed={}, fetch=[]): return feed, fetch diff --git a/tools/Dockerfile b/tools/Dockerfile index 359dd52c0726e9a421138bf3ecf4d6cff3b2036f..a39ce5bb76e411edeb94766d0c9aae23c6e7e62f 100644 --- a/tools/Dockerfile +++ b/tools/Dockerfile @@ -1,24 +1,8 @@ -FROM centos:centos6.10 -RUN yum -y install wget \ - && wget http://people.centos.org/tru/devtools-2/devtools-2.repo -O /etc/yum.repos.d/devtoolset-2.repo \ - && yum -y install devtoolset-2-gcc devtoolset-2-gcc-c++ devtoolset-2-binutils \ - && source /opt/rh/devtoolset-2/enable \ - && echo "source /opt/rh/devtoolset-2/enable" >> /etc/profile \ - && yum -y install git openssl-devel curl-devel bzip2-devel \ - && wget https://cmake.org/files/v3.5/cmake-3.5.2.tar.gz \ - && tar xvf cmake-3.5.2.tar.gz \ - && cd cmake-3.5.2 \ - && ./bootstrap --prefix=/usr \ - && make \ - && make install \ - && cd .. \ - && rm -r cmake-3.5.2* \ - && wget https://dl.google.com/go/go1.12.12.linux-amd64.tar.gz \ - && tar -xzvf go1.12.12.linux-amd64.tar.gz \ - && mv go /usr/local/go \ - && rm go1.12.12.linux-amd64.tar.gz \ - && echo "export GOROOT=/usr/local/go" >> /root/.bashrc \ - && echo "export GOPATH=$HOME/go" >> /root/.bashrc \ - && echo "export PATH=$PATH:/usr/local/go/bin" >> /root/.bashrc - +FROM centos:7.3.1611 +RUN yum -y install wget && \ + yum -y install epel-release && yum -y install patchelf && \ + yum -y install gcc make python-devel && \ + yum clean all && \ + curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py && \ + python get-pip.py && rm get-pip.py diff --git a/tools/Dockerfile.devel b/tools/Dockerfile.devel new file mode 100644 index 0000000000000000000000000000000000000000..a4b5b5fe48b5c4d5c74d66dc688fa5d594a33266 --- /dev/null +++ b/tools/Dockerfile.devel @@ -0,0 +1,22 @@ +FROM centos:7.3.1611 +RUN yum -y install wget >/dev/null \ + && yum -y install gcc gcc-c++ make glibc-static which >/dev/null \ + && yum -y install git openssl-devel curl-devel bzip2-devel python-devel >/dev/null \ + && wget https://cmake.org/files/v3.2/cmake-3.2.0-Linux-x86_64.tar.gz >/dev/null \ + && tar xzf cmake-3.2.0-Linux-x86_64.tar.gz \ + && mv cmake-3.2.0-Linux-x86_64 /usr/local/cmake3.2.0 \ + && echo 'export PATH=/usr/local/cmake3.2.0/bin:$PATH' >> /root/.bashrc \ + && rm cmake-3.2.0-Linux-x86_64.tar.gz \ + && wget https://dl.google.com/go/go1.14.linux-amd64.tar.gz >/dev/null \ + && tar xzf go1.14.linux-amd64.tar.gz \ + && mv go /usr/local/go \ + && echo 'export GOROOT=/usr/local/go' >> /root/.bashrc \ + && echo 'export PATH=/usr/local/go/bin:$PATH' >> /root/.bashrc \ + && rm go1.14.linux-amd64.tar.gz \ + && yum -y install python-devel sqlite-devel >/dev/null \ + && curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py >/dev/null \ + && python get-pip.py >/dev/null \ + && pip install google protobuf setuptools wheel flask >/dev/null \ + && rm get-pip.py \ + && yum -y install epel-release && yum -y install patchelf \ + && yum clean all diff --git a/tools/Dockerfile.gpu b/tools/Dockerfile.gpu index 5258854691866ab9357a947f42081ae8db6984d7..427ae83bcb805ec70c1e6d575e84234f17e9fb30 100644 --- a/tools/Dockerfile.gpu +++ b/tools/Dockerfile.gpu @@ -1,11 +1,15 @@ -FROM paddlepaddle/paddle_manylinux_devel:cuda9.0_cudnn7 -RUN yum -y install git openssl-devel curl-devel bzip2-devel \ - && wget https://dl.google.com/go/go1.12.12.linux-amd64.tar.gz \ - && tar -xzvf go1.12.12.linux-amd64.tar.gz \ - && rm -rf /usr/local/go \ - && mv go /usr/local/go \ - && rm go1.12.12.linux-amd64.tar.gz \ - && echo "GOROOT=/usr/local/go" >> /root/.bashrc \ - && echo "GOPATH=$HOME/go" >> /root/.bashrc \ - && echo "PATH=$PATH:$GOROOT/bin" >> /root/.bashrc +FROM nvidia/cuda:9.0-cudnn7-runtime-centos7 +RUN yum -y install wget && \ + yum -y install epel-release && yum -y install patchelf && \ + yum -y install gcc make python-devel && \ + yum -y install libSM-1.2.2-2.el7.x86_64 --setopt=protected_multilib=false && \ + yum -y install libXrender-0.9.10-1.el7.x86_64 --setopt=protected_multilib=false && \ + yum -y install libXext-1.3.3-3.el7.x86_64 --setopt=protected_multilib=false && \ + yum clean all && \ + curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py && \ + python get-pip.py && rm get-pip.py && \ + ln -s /usr/local/cuda-9.0/lib64/libcublas.so.9.0 /usr/local/cuda-9.0/lib64/libcublas.so && \ + echo 'export LD_LIBRARY_PATH=/usr/local/cuda/lib64':$LD_LIBRARY_PATH >> /root/.bashrc && \ + ln -s /usr/local/cuda-9.0/targets/x86_64-linux/lib/libcudnn.so.7 /usr/local/cuda-9.0/targets/x86_64-linux/lib/libcudnn.so && \ + echo 'export LD_LIBRARY_PATH=/usr/local/cuda-9.0/targets/x86_64-linux/lib:$LD_LIBRARY_PATH' >> /root/.bashrc diff --git a/tools/serving_build.sh b/tools/serving_build.sh index 163f4f74429066581aa17cc78b3ab00947ba4d77..b810e3139803bd363c771c6f655cef6595177dc8 100644 --- a/tools/serving_build.sh +++ b/tools/serving_build.sh @@ -83,7 +83,7 @@ function python_test_fit_a_line() { check_cmd "python test_client.py uci_housing_client/serving_client_conf.prototxt > /dev/null" ps -ef | grep "paddle_serving_server" | grep -v grep | awk '{print $2}' | xargs kill # test web - check_cmd "python -m paddle_serving_server.web_serve --model uci_housing_model/ --name uci --port 9399 --name uci > /dev/null &" + check_cmd "python -m paddle_serving_server.serve --model uci_housing_model/ --name uci --port 9399 --name uci > /dev/null &" sleep 5 check_cmd "curl -H \"Content-Type:application/json\" -X POST -d '{\"x\": [0.0137, -0.1136, 0.2553, -0.0692, 0.0582, -0.0727, -0.1583, -0.0584, 0.6283, 0.4919, 0.1856, 0.0795, -0.0332], \"fetch\":[\"price\"]}' http://127.0.0.1:9399/uci/prediction" ps -ef | grep "paddle_serving_server" | grep -v grep | awk '{print $2}' | xargs kill