diff --git a/README.md b/README.md index d018db0a1f0a358bde750da0075b1736b15a7d39..2fdc83db96d1b418aabddabe35f9709e2c72f810 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,8 @@ pip install paddle-serving-server-gpu # GPU You may need to use a domestic mirror source (in China, you can use the Tsinghua mirror source, add `-i https://pypi.tuna.tsinghua.edu.cn/simple` to pip command) to speed up the download. +If you need install modules compiled with develop branch, please download packages from [latest packages list](./doc/LATEST_PACKAGES.md) and install with `pip install` command. + Client package support Centos 7 and Ubuntu 18, or you can use HTTP service without install client.

Quick Start Example

diff --git a/README_CN.md b/README_CN.md index 3e39e1854c9fda8545172dfb7679fde881827741..547a50e7a430f3afb3a69eae211ed87cb248a268 100644 --- a/README_CN.md +++ b/README_CN.md @@ -57,6 +57,8 @@ pip install paddle-serving-server-gpu # GPU 您可能需要使用国内镜像源(例如清华源, 在pip命令中添加`-i https://pypi.tuna.tsinghua.edu.cn/simple`)来加速下载。 +如果需要使用develop分支编译的安装包,请从[最新安装包列表](./doc/LATEST_PACKAGES.md)中获取下载地址进行下载,使用`pip install`命令进行安装。 + 客户端安装包支持Centos 7和Ubuntu 18,或者您可以使用HTTP服务,这种情况下不需要安装客户端。

快速启动示例

diff --git a/doc/LATEST_PACKAGES.md b/doc/LATEST_PACKAGES.md new file mode 100644 index 0000000000000000000000000000000000000000..8756743a5c23778ea2d4753a693a272d5f6eb992 --- /dev/null +++ b/doc/LATEST_PACKAGES.md @@ -0,0 +1,47 @@ +# Latest Wheel Packages + +## CPU server +### Python 3 +``` +https://paddle-serving.bj.bcebos.com/whl/paddle_serving_server-0.3.0-py3-none-any.whl +``` + +### Python 2 +``` +https://paddle-serving.bj.bcebos.com/whl/paddle_serving_server-0.3.0-py2-none-any.whl +``` + +## GPU server +### Python 3 +``` +https://paddle-serving.bj.bcebos.com/whl/paddle_serving_server_gpu-0.3.0-py3-none-any.whl +``` +### Python 2 +``` +https://paddle-serving.bj.bcebos.com/whl/paddle_serving_server_gpu-0.3.0-py2-none-any.whl +``` + +## Client +### Python 3.7 +``` +https://paddle-serving.bj.bcebos.com/whl/paddle_serving_client-0.3.0-cp37-none-manylinux1_x86_64.whl +``` +### Python 3.6 +``` +https://paddle-serving.bj.bcebos.com/whl/paddle_serving_client-0.3.0-cp36-none-manylinux1_x86_64.whl +``` +### Python 2.7 +``` +https://paddle-serving.bj.bcebos.com/whl/paddle_serving_client-0.3.0-cp27-none-manylinux1_x86_64.whl +``` + +## App +### Python 3 +``` +https://paddle-serving.bj.bcebos.com/whl/paddle_serving_app-0.1.0-py3-none-any.whl +``` + +### Python 2 +``` +https://paddle-serving.bj.bcebos.com/whl/paddle_serving_app-0.1.0-py2-none-any.whl +``` diff --git a/python/examples/bert/test_multi_fetch_client.py b/python/examples/bert/test_multi_fetch_client.py new file mode 100644 index 0000000000000000000000000000000000000000..c15c4d4deaf282c432ff0990ee03c6e80daeee74 --- /dev/null +++ b/python/examples/bert/test_multi_fetch_client.py @@ -0,0 +1,43 @@ +# 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 +from paddle_serving_app.reader import ChineseBertReader +import sys + +client = Client() +client.load_client_config("./bert_seq32_client/serving_client_conf.prototxt") +client.connect(["127.0.0.1:9292"]) + +reader = ChineseBertReader({"max_seq_len": 32}) +fetch = ["sequence_10", "sequence_12", "pooled_output"] +expected_shape = { + "sequence_10": (4, 32, 768), + "sequence_12": (4, 32, 768), + "pooled_output": (4, 768) +} +batch_size = 4 +feed_batch = [] + +for line in sys.stdin: + feed = reader.process(line) + if len(feed_batch) < batch_size: + feed_batch.append(feed) + else: + fetch_map = client.predict(feed=feed_batch, fetch=fetch) + feed_batch = [] + for var_name in fetch: + if fetch_map[var_name].shape != expected_shape[var_name]: + print("fetch var {} shape error.".format(var_name)) + sys.exit(1) diff --git a/python/examples/fit_a_line/test_multi_process_client.py b/python/examples/fit_a_line/test_multi_process_client.py new file mode 100644 index 0000000000000000000000000000000000000000..46ba3b60b5ae09b568868531d32234ade50d8556 --- /dev/null +++ b/python/examples/fit_a_line/test_multi_process_client.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_client import Client +from paddle_serving_client.utils import MultiThreadRunner +import paddle + + +def single_func(idx, resource): + client = Client() + client.load_client_config( + "./uci_housing_client/serving_client_conf.prototxt") + client.connect(["127.0.0.1:9293", "127.0.0.1:9292"]) + test_reader = paddle.batch( + paddle.reader.shuffle( + paddle.dataset.uci_housing.test(), buf_size=500), + batch_size=1) + for data in test_reader(): + fetch_map = client.predict(feed={"x": data[0][0]}, fetch=["price"]) + return [[0]] + + +multi_thread_runner = MultiThreadRunner() +thread_num = 4 +result = multi_thread_runner.run(single_func, thread_num, {}) diff --git a/python/examples/fit_a_line/test_py_client.py b/python/examples/fit_a_line/test_py_client.py index 57ef3b405dfb94ebbdf398c7b2f28b617a51dab6..76fee2804daf6e98d0cb12a562e8b69ffa97742b 100644 --- a/python/examples/fit_a_line/test_py_client.py +++ b/python/examples/fit_a_line/test_py_client.py @@ -29,11 +29,11 @@ x = np.array( lp = LineProfiler() lp_wrapper = lp(client.predict) -for i in range(3): +for i in range(1): fetch_map = lp_wrapper( feed={"x": x}, fetch_with_type={"combine_op_output": "float"}) # fetch_map = client.predict( # feed={"x": x}, fetch_with_type={"combine_op_output": "float"}) print(fetch_map) -lp.print_stats() +#lp.print_stats() diff --git a/python/examples/fit_a_line/test_py_server.py b/python/examples/fit_a_line/test_py_server.py index 863ac55040f0b60aade4e2f6d103d7a7d34558ed..ff4542560a455af4b8256c8daf9b2c62ac5d8568 100644 --- a/python/examples/fit_a_line/test_py_server.py +++ b/python/examples/fit_a_line/test_py_server.py @@ -72,7 +72,9 @@ cnn_op = UciOp( client_config="uci_housing_client/serving_client_conf.prototxt", server_name="127.0.0.1:9393", fetch_names=["price"], - concurrency=1) + concurrency=1, + timeout=0.01, + retry=2) bow_op = UciOp( name="bow", @@ -86,7 +88,9 @@ bow_op = UciOp( client_config="uci_housing_client/serving_client_conf.prototxt", server_name="127.0.0.1:9393", fetch_names=["price"], - concurrency=1) + concurrency=1, + timeout=-1, + retry=1) combine_op = CombineOp( name="combine", @@ -94,12 +98,14 @@ combine_op = CombineOp( in_dtype='float', outputs=[out_channel], out_dtype='float', - concurrency=1) + concurrency=1, + timeout=-1, + retry=1) logging.info(read_channel.debug()) logging.info(combine_channel.debug()) logging.info(out_channel.debug()) -pyserver = PyServer(profile=False) +pyserver = PyServer(profile=False, retry=1) pyserver.add_channel(read_channel) pyserver.add_channel(combine_channel) pyserver.add_channel(out_channel) diff --git a/python/examples/senta/get_data.sh b/python/examples/senta/get_data.sh index fcd060f42aa2386e841f122c851394fc472d7f5b..7fd5c3e21880c44f27c4f4a037be87dc24790bc4 100644 --- a/python/examples/senta/get_data.sh +++ b/python/examples/senta/get_data.sh @@ -1,7 +1,7 @@ wget https://paddle-serving.bj.bcebos.com/paddle_hub_models/text/SentimentAnalysis/senta_bilstm.tar.gz --no-check-certificate tar -xzvf senta_bilstm.tar.gz wget https://paddle-serving.bj.bcebos.com/paddle_hub_models/text/LexicalAnalysis/lac.tar.gz --no-check-certificate -tar -xzvf lac_model.tar.gz +tar -xzvf lac.tar.gz wget https://paddle-serving.bj.bcebos.com/reader/lac/lac_dict.tar.gz --no-check-certificate tar -xzvf lac_dict.tar.gz wget https://paddle-serving.bj.bcebos.com/reader/senta/vocab.txt --no-check-certificate diff --git a/python/paddle_serving_server/pyserver.py b/python/paddle_serving_server/pyserver.py index 29ff56c422f59c9795e47ebe14402ff06634bf5b..420df4ef5079cd63ebc411fd157b1d5cf14b2a21 100644 --- a/python/paddle_serving_server/pyserver.py +++ b/python/paddle_serving_server/pyserver.py @@ -42,12 +42,16 @@ class _TimeProfiler(object): self._enable = enable def record(self, name_with_tag): + if self._enable is False: + return name_with_tag = name_with_tag.split("_") tag = name_with_tag[-1] name = '_'.join(name_with_tag[:-1]) self._time_record.put((name, tag, int(round(time.time() * 1000000)))) def print_profile(self): + if self._enable is False: + return sys.stderr.write(self._print_head) tmp = {} while not self._time_record.empty(): @@ -267,7 +271,8 @@ class Op(object): server_name=None, fetch_names=None, concurrency=1, - timeout=-1): + timeout=-1, + retry=2): self._run = False # TODO: globally unique check self._name = name # to identify the type of OP, it must be globally unique @@ -285,6 +290,7 @@ class Op(object): self._server_port = server_port self._device = device self._timeout = timeout + self._retry = retry def set_client(self, client_config, server_name, fetch_names): self._client = Client() @@ -387,24 +393,35 @@ class Op(object): error_info = None if self.with_serving(): - _profiler.record("{}{}-midp_0".format(self._name, - concurrency_idx)) - if self._time > 0: - try: - data = func_timeout.func_timeout( - self._time, self.midprocess, args=(data, )) - except func_timeout.FunctionTimedOut: - logging.error("error: timeout") - error_info = "{}({}): timeout".format( - self._name, concurrency_idx) - except Exception as e: - logging.error("error: {}".format(e)) - error_info = "{}({}): {}".format(self._name, - concurrency_idx, e) - else: - data = self.midprocess(data) - _profiler.record("{}{}-midp_1".format(self._name, - concurrency_idx)) + for i in range(self._retry): + _profiler.record("{}{}-midp_0".format(self._name, + concurrency_idx)) + if self._timeout > 0: + try: + middata = func_timeout.func_timeout( + self._timeout, + self.midprocess, + args=(data, )) + except func_timeout.FunctionTimedOut: + logging.error("error: timeout") + error_info = "{}({}): timeout".format( + self._name, concurrency_idx) + except Exception as e: + logging.error("error: {}".format(e)) + error_info = "{}({}): {}".format( + self._name, concurrency_idx, e) + else: + middata = self.midprocess(data) + _profiler.record("{}{}-midp_1".format(self._name, + concurrency_idx)) + if error_info is None: + data = middata + break + if i + 1 < self._retry: + error_info = None + logging.warn( + self._log("warn: timeout, retry({})".format(i + + 1))) _profiler.record("{}{}-postp_0".format(self._name, concurrency_idx)) @@ -509,6 +526,7 @@ class GeneralPythonService( data = python_service_channel_pb2.ChannelData() data_id = self._get_next_id() data.id = data_id + data.is_error = 0 for idx, name in enumerate(request.feed_var_names): logging.debug( self._log('name: {}'.format(request.feed_var_names[idx]))) diff --git a/tools/serving_build.sh b/tools/serving_build.sh index 43e55174ab30374d853ed1bb25aa4a9cc637afd5..8e78e13ef8e86b55af6a90df1b9235611508c0ba 100644 --- a/tools/serving_build.sh +++ b/tools/serving_build.sh @@ -331,6 +331,75 @@ function python_test_bert() { cd .. } +function python_test_multi_fetch() { + # pwd: /Serving/python/examples + local TYPT=$1 + export SERVING_BIN=${SERVING_WORKDIR}/build-server-${TYPE}/core/general-server/serving + cd bert # pwd: /Serving/python/examples/bert + case $TYPE in + CPU) + #download model (max_seq_len=32) + wget https://paddle-serving.bj.bcebos.com/bert_example/bert_multi_fetch.tar.gz + tar -xzvf bert_multi_fetch.tar.gz + check_cmd "python -m paddle_serving_server.serve --model bert_seq32_model --port 9292 &" + sleep 5 + check_cmd "head -n 8 data-c.txt | python test_multi_fetch_client.py" + kill_server_process + echo "bert mutli fetch RPC inference pass" + ;; + GPU) + #download model (max_seq_len=32) + wget https://paddle-serving.bj.bcebos.com/bert_example/bert_multi_fetch.tar.gz + tar -xzvf bert_multi_fetch.tar.gz + check_cmd "python -m paddle_serving_server_gpu.serve --model bert_seq32_model --port 9292 --gpu_ids 0 &" + sleep 5 + check_cmd "head -n 8 data-c.txt | python test_multi_fetch_client.py" + kill_server_process + echo "bert mutli fetch RPC inference pass" + ;; + *) + echo "error type" + exit 1 + ;; + esac + echo "test multi fetch $TYPE finished as expected." + unset SERVING_BIN + cd .. +} + +function python_test_multi_process(){ + # pwd: /Serving/python/examples + local TYPT=$1 + export SERVING_BIN=${SERVING_WORKDIR}/build-server-${TYPE}/core/general-server/serving + cd fit_a_line # pwd: /Serving/python/examples/fit_a_line + sh get_data.sh + case $TYPE in + CPU) + check_cmd "python -m paddle_serving_server.serve --model uci_housing_model --port 9292 &" + check_cmd "python -m paddle_serving_server.serve --model uci_housing_model --port 9293 &" + sleep 5 + check_cmd "python test_multi_process_client.py" + kill_server_process + echo "bert mutli rpc RPC inference pass" + ;; + GPU) + check_cmd "python -m paddle_serving_server_gpu.serve --model uci_housing_model --port 9292 --gpu_ids 0 &" + check_cmd "python -m paddle_serving_server_gpu.serve --model uci_housing_model --port 9293 --gpu_ids 0 &" + sleep 5 + check_cmd "python test_multi_process_client.py" + kill_server_process + echo "bert mutli process RPC inference pass" + ;; + *) + echo "error type" + exit 1 + ;; + esac + echo "test multi process $TYPE finished as expected." + unset SERVING_BIN + cd .. +} + function python_test_imdb() { # pwd: /Serving/python/examples local TYPE=$1 @@ -436,7 +505,9 @@ function python_run_test() { python_run_criteo_ctr_with_cube $TYPE # pwd: /Serving/python/examples python_test_bert $TYPE # pwd: /Serving/python/examples python_test_imdb $TYPE # pwd: /Serving/python/examples - python_test_lac $TYPE + python_test_lac $TYPE # pwd: /Serving/python/examples + python_test_multi_process $TYPE # pwd: /Serving/python/examples + python_test_multi_fetch $TYPE # pwd: /Serving/python/examples echo "test python $TYPE part finished as expected." cd ../.. # pwd: /Serving }