diff --git a/python/examples/imagenet/README.md b/python/examples/imagenet/README.md index ad8b12b5b..7edcd0201 100644 --- a/python/examples/imagenet/README.md +++ b/python/examples/imagenet/README.md @@ -47,3 +47,13 @@ client send inference request python resnet50_rpc_client.py ResNet50_vd_client_config/serving_client_conf.prototxt ``` *the port of server side in this example is 9696 + +### Launch Paddle Serving on Kubernetes + +Paddle Serving support deployment on Kubernetes (K8S) clusters. From `imagenet_k8s_rpc.yaml` we define Serving as K8S Deployment and Service. User can deploy Serving on containers and expose internal or external service. + +We strongly recommend [Baidu Cloud CCE Cluster](https://cloud.baidu.com/search.html?q=CCE) + +``` +kubectl apply -f imagenet_k8s_rpc.yaml +``` diff --git a/python/examples/imagenet/README_CN.md b/python/examples/imagenet/README_CN.md index 8650d51a6..026690103 100644 --- a/python/examples/imagenet/README_CN.md +++ b/python/examples/imagenet/README_CN.md @@ -47,3 +47,13 @@ client端进行预测 python resnet50_rpc_client.py ResNet50_vd_client_config/serving_client_conf.prototxt ``` *server端示例中服务端口为9696端口 + +### K8S启动 + +还可以运用K8S启动,在`imagenet_k8s_rpc.yaml`中定义了Serving的Deployment和Service,用户可以在K8S集群上启动Deployment并且通过Service对外暴露服务,用户可以在此基础上进行二次开发。 + +推荐百度云的[CCE(K8S)集群](https://cloud.baidu.com/search.html?q=CCE) + +``` +kubectl apply -f imagenet_k8s_rpc.yaml +``` diff --git a/python/examples/imagenet/imagenet_k8s_rpc.yaml b/python/examples/imagenet/imagenet_k8s_rpc.yaml new file mode 100644 index 000000000..da93b42cb --- /dev/null +++ b/python/examples/imagenet/imagenet_k8s_rpc.yaml @@ -0,0 +1,55 @@ +# 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. + +apiVersion: apps/v1beta1 +kind: Deployment +metadata: + name: paddleserving + labels: + app: paddleserving +spec: + replicas: 1 + template: + metadata: + name: paddleserving + labels: + app: paddleserving + spec: + containers: + - name: paddleserving + image: hub.baidubce.com/paddlepaddle/serving:latest + imagePullPolicy: Always + workingDir: / + command: ['/bin/bash', '-c'] + args: ['pip install -U paddle-serving-server paddle-serving-client paddle-serving-app && \ + python -m paddle_serving_app.package --get_model resnet_v2_50_imagenet && \ + tar xf resnet_v2_50_imagenet.tar.gz && \ + python -m paddle_serving_server.serve --model resnet_v2_50_imagenet_model/ --port 9696'] + ports: + - containerPort: 9696 + name: serving + +--- + +apiVersion: v1 +kind: Service +metadata: + name: paddleserving +spec: + ports: + - name: paddleserving + port: 9696 + targetPort: 9696 + selector: + app: paddleserving diff --git a/python/examples/pipeline/faster_rcnn/000000570688.jpg b/python/examples/pipeline/faster_rcnn/000000570688.jpg new file mode 100644 index 000000000..cb304bd56 Binary files /dev/null and b/python/examples/pipeline/faster_rcnn/000000570688.jpg differ diff --git a/python/examples/pipeline/faster_rcnn/benchmark.py b/python/examples/pipeline/faster_rcnn/benchmark.py new file mode 100644 index 000000000..9fdb48f7e --- /dev/null +++ b/python/examples/pipeline/faster_rcnn/benchmark.py @@ -0,0 +1,107 @@ +import sys +import os +import yaml +import requests +import time +import json +import cv2 +import base64 +try: + from paddle_serving_server_gpu.pipeline import PipelineClient +except ImportError: + from paddle_serving_server.pipeline import PipelineClient +import numpy as np +from paddle_serving_client.utils import MultiThreadRunner +from paddle_serving_client.utils import benchmark_args, show_latency + +def cv2_to_base64(image): + return base64.b64encode(image).decode('utf8') + +def parse_benchmark(filein, fileout): + with open(filein, "r") as fin: + res = yaml.load(fin) + del_list = [] + for key in res["DAG"].keys(): + if "call" in key: + del_list.append(key) + for key in del_list: + del res["DAG"][key] + with open(fileout, "w") as fout: + yaml.dump(res, fout, default_flow_style=False) + +def gen_yml(device): + fin = open("config.yml", "r") + config = yaml.load(fin) + fin.close() + config["dag"]["tracer"] = {"interval_s": 10} + if device == "gpu": + config["op"]["bert"]["local_service_conf"]["device_type"] = 1 + config["op"]["bert"]["local_service_conf"]["devices"] = "2" + with open("config2.yml", "w") as fout: + yaml.dump(config, fout, default_flow_style=False) + +def run_http(idx, batch_size): + print("start thread ({})".format(idx)) + url = "http://127.0.0.1:18082/faster_rcnn/prediction" + with open(os.path.join(".", "000000570688.jpg"), 'rb') as file: + image_data1 = file.read() + image = cv2_to_base64(image_data1) + + start = time.time() + for i in range(10): + data = {"key": [], "value": []} + for j in range(batch_size): + data["key"].append("image_" + str(j)) + data["value"].append(image) + r = requests.post(url=url, data=json.dumps(data)) + print("done") + end = time.time() + return [[end - start]] + +def multithread_http(thread, batch_size): + multi_thread_runner = MultiThreadRunner() + result = multi_thread_runner.run(run_http , thread, batch_size) + +def run_rpc(thread, batch_size): + client = PipelineClient() + client.connect(['127.0.0.1:9998']) + with open("data-c.txt", 'r') as fin: + start = time.time() + lines = fin.readlines() + start_idx = 0 + while start_idx < len(lines): + end_idx = min(len(lines), start_idx + batch_size) + feed = {} + for i in range(start_idx, end_idx): + feed[str(i - start_idx)] = lines[i] + ret = client.predict(feed_dict=feed, fetch=["res"]) + start_idx += batch_size + if start_idx > 1000: + break + end = time.time() + return [[end - start]] + + +def multithread_rpc(thraed, batch_size): + multi_thread_runner = MultiThreadRunner() + result = multi_thread_runner.run(run_rpc , thread, batch_size) + +if __name__ == "__main__": + if sys.argv[1] == "yaml": + mode = sys.argv[2] # brpc/ local predictor + thread = int(sys.argv[3]) + device = sys.argv[4] + gen_yml(device) + elif sys.argv[1] == "run": + mode = sys.argv[2] # http/ rpc + thread = int(sys.argv[3]) + batch_size = int(sys.argv[4]) + if mode == "http": + multithread_http(thread, batch_size) + elif mode == "rpc": + multithread_rpc(thread, batch_size) + elif sys.argv[1] == "dump": + filein = sys.argv[2] + fileout = sys.argv[3] + parse_benchmark(filein, fileout) + diff --git a/python/examples/pipeline/faster_rcnn/benchmark.sh b/python/examples/pipeline/faster_rcnn/benchmark.sh new file mode 100644 index 000000000..7ff22a8b7 --- /dev/null +++ b/python/examples/pipeline/faster_rcnn/benchmark.sh @@ -0,0 +1,60 @@ +export FLAGS_profile_pipeline=1 +alias python3="python3.6" +modelname="bert" +# HTTP +ps -ef | grep web_service | awk '{print $2}' | xargs kill -9 +sleep 3 +python3 benchmark.py yaml local_predictor 1 cpu +rm -rf profile_log_$modelname +for thread_num in 1 +do + for batch_size in 1 2 + do + echo "----FasterRCNN thread num: $thread_num batch size: $batch_size mode:http ----" >>profile_log_$modelname + rm -rf PipelineServingLogs + rm -rf cpu_utilization.py + python3 web_service.py >web.log 2>&1 & + sleep 3 + nvidia-smi --id=2 --query-compute-apps=used_memory --format=csv -lms 100 > gpu_use.log 2>&1 & + nvidia-smi --id=2 --query-gpu=utilization.gpu --format=csv -lms 100 > gpu_utilization.log 2>&1 & + echo "import psutil\ncpu_utilization=psutil.cpu_percent(1,False)\nprint('CPU_UTILIZATION:', cpu_utilization)\n" > cpu_utilization.py + python3 benchmark.py run http $thread_num $batch_size + python3 cpu_utilization.py >>profile_log_$modelname + ps -ef | grep web_service | awk '{print $2}' | xargs kill -9 + python3 benchmark.py dump benchmark.log benchmark.tmp + mv benchmark.tmp benchmark.log + awk 'BEGIN {max = 0} {if(NR>1){if ($modelname > max) max=$modelname}} END {print "MAX_GPU_MEMORY:", max}' gpu_use.log >> profile_log_$modelname + awk 'BEGIN {max = 0} {if(NR>1){if ($modelname > max) max=$modelname}} END {print "GPU_UTILIZATION:", max}' gpu_utilization.log >> profile_log_$modelname + cat benchmark.log >> profile_log_$modelname + #rm -rf gpu_use.log gpu_utilization.log + done +done +# RPC +exit +ps -ef | grep web_service | awk '{print $2}' | xargs kill -9 +sleep 3 +python3 benchmark.py yaml local_predictor 1 gpu + +for thread_num in 1 8 16 +do + for batch_size in 1 10 100 + do + echo "----Bert thread num: $thread_num batch size: $batch_size mode:rpc ----" >>profile_log_$modelname + rm -rf PipelineServingLogs + rm -rf cpu_utilization.py + python3 web_service.py >web.log 2>&1 & + sleep 3 + nvidia-smi --id=2 --query-compute-apps=used_memory --format=csv -lms 100 > gpu_use.log 2>&1 & + nvidia-smi --id=2 --query-gpu=utilization.gpu --format=csv -lms 100 > gpu_utilization.log 2>&1 & + echo "import psutil\ncpu_utilization=psutil.cpu_percent(1,False)\nprint('CPU_UTILIZATION:', cpu_utilization)\n" > cpu_utilization.py + python3 benchmark.py run rpc $thread_num $batch_size + python3 cpu_utilization.py >>profile_log_$modelname + ps -ef | grep web_service | awk '{print $2}' | xargs kill -9 + python3 benchmark.py dump benchmark.log benchmark.tmp + mv benchmark.tmp benchmark.log + awk 'BEGIN {max = 0} {if(NR>1){if ($modelname > max) max=$modelname}} END {print "MAX_GPU_MEMORY:", max}' gpu_use.log >> profile_log_$modelname + awk 'BEGIN {max = 0} {if(NR>1){if ($modelname > max) max=$modelname}} END {print "GPU_UTILIZATION:", max}' gpu_utilization.log >> profile_log_$modelname + #rm -rf gpu_use.log gpu_utilization.log + cat benchmark.log >> profile_log_$modelname + done +done diff --git a/python/examples/pipeline/faster_rcnn/config.yml b/python/examples/pipeline/faster_rcnn/config.yml new file mode 100644 index 000000000..50f9298e0 --- /dev/null +++ b/python/examples/pipeline/faster_rcnn/config.yml @@ -0,0 +1,17 @@ +dag: + is_thread_op: false + tracer: + interval_s: 10 +http_port: 18082 +op: + faster_rcnn: + local_service_conf: + client_type: local_predictor + concurrency: 2 + device_type: 1 + devices: '2' + fetch_list: + - save_infer_model/scale_0.tmp_1 + model_config: serving_server/ +rpc_port: 9998 +worker_num: 20 diff --git a/python/examples/pipeline/faster_rcnn/label_list.txt b/python/examples/pipeline/faster_rcnn/label_list.txt new file mode 100644 index 000000000..941cb4e13 --- /dev/null +++ b/python/examples/pipeline/faster_rcnn/label_list.txt @@ -0,0 +1,80 @@ +person +bicycle +car +motorcycle +airplane +bus +train +truck +boat +traffic light +fire hydrant +stop sign +parking meter +bench +bird +cat +dog +horse +sheep +cow +elephant +bear +zebra +giraffe +backpack +umbrella +handbag +tie +suitcase +frisbee +skis +snowboard +sports ball +kite +baseball bat +baseball glove +skateboard +surfboard +tennis racket +bottle +wine glass +cup +fork +knife +spoon +bowl +banana +apple +sandwich +orange +broccoli +carrot +hot dog +pizza +donut +cake +chair +couch +potted plant +bed +dining table +toilet +tv +laptop +mouse +remote +keyboard +cell phone +microwave +oven +toaster +sink +refrigerator +book +clock +vase +scissors +teddy bear +hair drier +toothbrush diff --git a/python/examples/pipeline/faster_rcnn/pipeline_http_client.py b/python/examples/pipeline/faster_rcnn/pipeline_http_client.py new file mode 100644 index 000000000..7037afc2f --- /dev/null +++ b/python/examples/pipeline/faster_rcnn/pipeline_http_client.py @@ -0,0 +1,35 @@ +# 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.pipeline import PipelineClient +import numpy as np +import requests +import json +import cv2 +import base64 +import os + + +def cv2_to_base64(image): + return base64.b64encode(image).decode('utf8') + + +url = "http://127.0.0.1:18082/faster_rcnn/prediction" +with open(os.path.join(".", "000000570688.jpg"), 'rb') as file: + image_data1 = file.read() +image = cv2_to_base64(image_data1) + +for i in range(1): + data = {"key": ["image"], "value": [image]} + r = requests.post(url=url, data=json.dumps(data)) + print(r.json()) diff --git a/python/examples/pipeline/faster_rcnn/web_service.py b/python/examples/pipeline/faster_rcnn/web_service.py new file mode 100644 index 000000000..1f483a0e6 --- /dev/null +++ b/python/examples/pipeline/faster_rcnn/web_service.py @@ -0,0 +1,71 @@ +# 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. +try: + from paddle_serving_server_gpu.web_service import WebService, Op +except ImportError: + from paddle_serving_server.web_service import WebService, Op +import logging +import numpy as np +import sys +import cv2 +from paddle_serving_app.reader import * +import base64 + +class FasterRCNNOp(Op): + def init_op(self): + self.img_preprocess = Sequential([ + BGR2RGB(), Div(255.0), + Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225], False), + Resize((640, 640)), Transpose((2, 0, 1)) + ]) + self.img_postprocess = RCNNPostprocess("label_list.txt", "output") + + def preprocess(self, input_dicts, data_id, log_id): + (_, input_dict), = input_dicts.items() + imgs = [] + print("keys", input_dict.keys()) + for key in input_dict.keys(): + data = base64.b64decode(input_dict[key].encode('utf8')) + data = np.fromstring(data, np.uint8) + im = cv2.imdecode(data, cv2.IMREAD_COLOR) + im = self.img_preprocess(im) + imgs.append({ + "image": im[np.newaxis,:], + "im_shape": np.array(list(im.shape[1:])).reshape(-1)[np.newaxis,:], + "scale_factor": np.array([1.0, 1.0]).reshape(-1)[np.newaxis,:], + }) + feed_dict = { + "image": np.concatenate([x["image"] for x in imgs], axis=0), + "im_shape": np.concatenate([x["im_shape"] for x in imgs], axis=0), + "scale_factor": np.concatenate([x["scale_factor"] for x in imgs], axis=0) + } + for key in feed_dict.keys(): + print(key, feed_dict[key].shape) + return feed_dict, False, None, "" + + def postprocess(self, input_dicts, fetch_dict, log_id): + #print(fetch_dict) + res_dict = {"bbox_result": str(self.img_postprocess(fetch_dict))} + return res_dict, None, "" + + +class FasterRCNNService(WebService): + def get_pipeline_response(self, read_op): + faster_rcnn_op = FasterRCNNOp(name="faster_rcnn", input_ops=[read_op]) + return faster_rcnn_op + + +fasterrcnn_service = FasterRCNNService(name="faster_rcnn") +fasterrcnn_service.prepare_pipeline_config("config2.yml") +fasterrcnn_service.run_service() diff --git a/tools/Dockerfile.runtime_template b/tools/Dockerfile.runtime_template new file mode 100644 index 000000000..abdca4eaa --- /dev/null +++ b/tools/Dockerfile.runtime_template @@ -0,0 +1,56 @@ +# Dockerfile template +FROM <> + +RUN apt-get update && \ + apt-get install -y make build-essential + +RUN apt-get update && \ + apt-get install -y wget tar xz-utils bzip2 libcurl4-openssl-dev \ + curl sed grep zlib1g-dev libreadline-gplv2-dev libncursesw5-dev libssl-dev libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev && \ + apt-get clean -y + +WORKDIR /usr/bin + COPY tools/dockerfile/build_scripts /build_scripts + RUN bash /build_scripts/install_gcc.sh gcc82 && rm -rf /build_scripts + RUN cp gcc gcc.bak && cp g++ g++.bak && rm gcc && rm g++ + RUN ln -s /usr/local/gcc-8.2/bin/gcc /usr/local/bin/gcc + RUN ln -s /usr/local/gcc-8.2/bin/g++ /usr/local/bin/g++ + RUN ln -s /usr/local/gcc-8.2/bin/gcc /usr/bin/gcc + RUN ln -s /usr/local/gcc-8.2/bin/g++ /usr/bin/g++ + ENV PATH=/usr/local/gcc-8.2/bin:$PATH + +# install python +WORKDIR /home + COPY tools/dockerfile/build_scripts /build_scripts + RUN bash /build_scripts/install_python.sh <> && rm -rf /build_scripts + # Other + +# install whl and bin +WORKDIR /home + COPY tools/dockerfile/build_scripts /build_scripts + RUN bash /build_scripts/install_whl.sh 0.5.0 2.0.0 <> <> && rm -rf /build_scripts + +# install tensorrt +WORKDIR /home + COPY tools/dockerfile/build_scripts /build_scripts + RUN bash /build_scripts/install_trt.sh && rm -rf /build_scripts + +# install go +RUN wget -qO- https://dl.google.com/go/go1.14.linux-amd64.tar.gz | \ + tar -xz -C /usr/local && \ + mkdir /root/go && \ + mkdir /root/go/bin && \ + mkdir /root/go/src && \ + echo "GOROOT=/usr/local/go" >> /root/.bashrc && \ + echo "GOPATH=/root/go" >> /root/.bashrc && \ + echo "PATH=/usr/local/go/bin:/root/go/bin:$PATH" >> /root/.bashrc + +RUN wget https://paddle-serving.bj.bcebos.com/others/centos_ssl.tar && \ + tar xf centos_ssl.tar && rm -rf centos_ssl.tar && \ + mv libcrypto.so.1.0.2k /usr/lib/libcrypto.so.1.0.2k && mv libssl.so.1.0.2k /usr/lib/libssl.so.1.0.2k && \ + ln -sf /usr/lib/libcrypto.so.1.0.2k /usr/lib/libcrypto.so.10 && \ + ln -sf /usr/lib/libssl.so.1.0.2k /usr/lib/libssl.so.10 && \ + ln -sf /usr/lib/libcrypto.so.10 /usr/lib/libcrypto.so && \ + ln -sf /usr/lib/libssl.so.10 /usr/lib/libssl.so + +EXPOSE 22 diff --git a/tools/dockerfile/build_scripts/install_gcc.sh b/tools/dockerfile/build_scripts/install_gcc.sh index e75021b2a..bf0dd5f2e 100644 --- a/tools/dockerfile/build_scripts/install_gcc.sh +++ b/tools/dockerfile/build_scripts/install_gcc.sh @@ -39,6 +39,7 @@ if [ "$1" == "gcc82" ]; then ../gcc-8.2.0/configure --prefix=/usr/local/gcc-8.2 --enable-threads=posix --disable-checking --disable-multilib && \ make -j8 && make install cd .. && rm -rf temp_gcc82 + rm -rf gcc-8.2.0 gcc-8.2.0.tar.xz cp ${lib_so_6} ${lib_so_6}.bak && rm -f ${lib_so_6} && ln -s /usr/local/gcc-8.2/lib64/libgfortran.so.5 ${lib_so_5} && \ ln -s /usr/local/gcc-8.2/lib64/libstdc++.so.6 ${lib_so_6} && \ diff --git a/tools/dockerfile/build_scripts/install_python.sh b/tools/dockerfile/build_scripts/install_python.sh new file mode 100644 index 000000000..80d6554d8 --- /dev/null +++ b/tools/dockerfile/build_scripts/install_python.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +# 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. + +VERSION=$1 + +if [[ "$VERSION" == "2.7" ]];then + wget -q https://www.python.org/ftp/python/2.7.15/Python-2.7.15.tgz && tar -xvf Python-2.7.15.tgz && cd Python-2.7.15 + ./configure --enable-unicode=ucs4 --enable-shared CFLAGS=-fPIC --prefix=/usr/local/ && make && make install -j8 > /dev/null && make altinstall > /dev/null && ldconfig + cd .. && rm -rf Python-2.7.15* + wget https://bootstrap.pypa.io/pip/2.7/get-pip.py + python2.7 get-pip.py + rm -rf get-pip.py +elif [[ "$VERSION" == "3.6" ]];then + wget -q https://www.python.org/ftp/python/3.6.8/Python-3.6.8.tgz && \ + tar -xzf Python-3.6.8.tgz && cd Python-3.6.8 && \ + CFLAGS="-Wformat" ./configure --prefix=/usr/local/ --enable-shared > /dev/null && \ + make -j8 > /dev/null && make altinstall > /dev/null && ldconfig + cd .. && rm -rf Python-3.6.8* +elif [[ "$VERSION" == "3.7" ]];then + wget -q https://www.python.org/ftp/python/3.7.0/Python-3.7.0.tgz && \ + tar -xzf Python-3.7.0.tgz && cd Python-3.7.0 && \ + CFLAGS="-Wformat" ./configure --prefix=/usr/local/ --enable-shared > /dev/null && \ + make -j8 > /dev/null && make altinstall > /dev/null && ldconfig + cd .. && rm -rf Python-3.7.0* +fi diff --git a/tools/dockerfile/build_scripts/install_whl.sh b/tools/dockerfile/build_scripts/install_whl.sh new file mode 100644 index 000000000..8d27e953b --- /dev/null +++ b/tools/dockerfile/build_scripts/install_whl.sh @@ -0,0 +1,56 @@ +#!/bin/bash + +# 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. + +SERVING_VERSION=$1 +PADDLE_VERSION=$2 +RUN_ENV=$3 # cpu/10.1 10.2 +PYTHON_VERSION=$4 + +client_release="paddle-serving-client==$SERVING_VERSION" +app_release="paddle-serving-app==0.3.1" +if [[ "$RUN_ENV" == "cpu" ]];then + server_release="paddle-serving-server==$SERVING_VERSION" + python$PYTHON_VERSION -m pip install $client_release $app_release $server_release + python$PYTHON_VERSION -m pip install paddlepaddle==${PADDLE_VERSION} + cd /usr/local/ + wget https://paddle-serving.bj.bcebos.com/bin/serving-cpu-noavx-openblas-${SERVING_VERSION}.tar.gz + tar xf serving-cpu-noavx-openblas-${SERVING_VERSION}.tar.gz + echo "export SERVING_BIN=$PWD/serving-cpu-noavx-openblas-${SERVING_VERSION}/serving">>/root/.bashrc + rm -rf serving-cpu-noavx-openblas-${SERVING_VERSION}.tar.gz + cd - +elif [[ "$RUN_ENV" == "cuda10.1" ]];then + server_release="paddle-serving-server-gpu==$SERVING_VERSION.post101" + python$PYTHON_VERSION -m pip install $client_release $app_release $server_release + python$PYTHON_VERSION -m pip install paddlepaddle-gpu==${PADDLE_VERSION} + cd /usr/local/ + wget https://paddle-serving.bj.bcebos.com/bin/serving-gpu-101-${SERVING_VERSION}.tar.gz + tar xf serving-gpu-101-${SERVING_VERSION}.tar.gz + echo "export SERVING_BIN=$PWD/serving-gpu-101-${SERVING_VERSION}/serving">>/root/.bashrc + rm -rf serving-gpu-101-${SERVING_VERSION}.tar.gz + cd - +elif [[ "$RUN_ENV" == "cuda10.2" ]];then + server_release="paddle-serving-server-gpu==$SERVING_VERSION.post102" + python$PYTHON_VERSION -m pip install $client_release $app_release $server_release + python$PYTHON_VERSION -m pip install paddlepaddle-gpu==${PADDLE_VERSION} + cd /usr/local/ + wget https://paddle-serving.bj.bcebos.com/bin/serving-gpu-102-${SERVING_VERSION}.tar.gz + tar xf serving-gpu-102-${SERVING_VERSION}.tar.gz + echo "export SERVING_BIN=$PWD/serving-gpu-102-${SERVING_VERSION}/serving">>/root/.bashrc + rm -rf serving-gpu-102-${SERVING_VERSION}.tar.gz + cd - +fi + + diff --git a/tools/generate_runtime_docker.sh b/tools/generate_runtime_docker.sh new file mode 100644 index 000000000..75a2baba1 --- /dev/null +++ b/tools/generate_runtime_docker.sh @@ -0,0 +1,80 @@ +#!/bin/sh + +#abort on error +set -e + +function usage +{ + echo "usage: arg_parse_example -a AN_ARG -s SOME_MORE_ARGS [-y YET_MORE_ARGS || -h]" + echo " "; + echo " --env : running env, cpu/cuda10.1/cuda10.2/cuda11"; + echo " --python : python version, 2.7/3.6/3.7 "; + echo " --serving : serving version(0.5.0)"; + echo " --paddle : paddle version(2.0.1)" + echo " --image_name : image name(default serving_runtime:env-python)" + echo " -h | --help : helper"; +} + +function parse_args +{ + # positional args + args=() + + # named args + while [ "$1" != "" ]; do + case "$1" in + --env ) env="$2"; shift;; + --python ) python="$2"; shift;; + --serving ) serving="$2"; shift;; + --paddle ) paddle="$2"; shift;; + --image_name ) image_name="$2"; shift;; + -h | --help ) usage; exit;; # quit and show usage + * ) args+=("$1") # if no match, add it to the positional args + esac + shift # move to next kv pair + done + # restore positional args + set -- "${args[@]}" + + # set positionals to vars + positional_1="${args[0]}" + positional_2="${args[1]}" + + # validate required args + if [[ -z "${paddle}" || -z "${env}" || -z "${python}" || -z "${serving}" ]]; then + echo "Invalid arguments" + usage + exit; + fi + + if [[ -z "${image_name}" ]]; then + image_name="serving_runtime:$env-$python" + echo "image_name is not assigned, so it will be set ($image_name)." + fi + +} + + +function run +{ + parse_args "$@" + + echo "named arg: env: $env" + if [ $env == "cpu" ]; then + base_image="ubuntu:16.04" + elif [ $env == "cuda10.1" ]; then + base_image="nvidia\/cuda:10.1-cudnn7-runtime-ubuntu16.04" + elif [ $env == "cuda10.2" ]; then + base_image="nvidia\/cuda:10.2-cudnn8-runtime-ubuntu16.04" + fi + echo "base image: $base_image" + echo "named arg: python: $python" + echo "named arg: serving: $serving" + echo "named arg: paddle: $paddle" + echo "named arg: image_name: $image_name" + + sed -e "s/<>/$base_image/g" -e "s/<>/$python/g" -e "s/<>/$env/g" Dockerfile.runtime_template > Dockerfile.tmp + docker build --build-arg ftp_proxy=http://172.19.57.45:3128 --build-arg https_proxy=http://172.19.57.45:3128 --build-arg http_proxy=http://172.19.57.45:3128 --build-arg HTTP_PROXY=http://172.19.57.45:3128 --build-arg HTTPS_PROXY=http://172.19.57.45:3128 -t $image_name -f Dockerfile.tmp . +} + +run "$@";