From 9c67653e343b16ae2db25642b3bdce61b7323faf Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 8 Aug 2022 15:24:36 +0800 Subject: [PATCH] support build cpu/gpu package (#75) * support build cpu/gpu package * remove useless modification --- CMakeLists.txt | 2 + .../fastdeploy/pybind/{main.cc => main.cc.in} | 2 +- fastdeploy/__init__.py | 51 +--- fastdeploy/c_lib_wrap.py.in | 59 +++++ fastdeploy/model.py | 2 +- fastdeploy/runtime.py | 2 +- fastdeploy/vision/biubug6/__init__.py | 2 +- fastdeploy/vision/deepcam/__init__.py | 2 +- fastdeploy/vision/deepinsight/__init__.py | 2 +- fastdeploy/vision/linzaer/__init__.py | 2 +- fastdeploy/vision/megvii/__init__.py | 2 +- fastdeploy/vision/meituan/__init__.py | 2 +- fastdeploy/vision/ppcls/__init__.py | 2 +- fastdeploy/vision/ppdet/__init__.py | 2 +- fastdeploy/vision/ppogg/__init__.py | 2 +- fastdeploy/vision/ppseg/__init__.py | 2 +- fastdeploy/vision/rangilyu/__init__.py | 2 +- fastdeploy/vision/ultralytics/__init__.py | 2 +- fastdeploy/vision/visualize/__init__.py | 2 +- fastdeploy/vision/wongkinyiu/__init__.py | 2 +- sdk_mannager/fastdeploy/__init__.py | 230 ++++++++++++++++++ sdk_mannager/fastdeploy/__main__.py | 18 ++ sdk_mannager/fastdeploy/download.py | 186 ++++++++++++++ sdk_mannager/requirements.txt | 2 + sdk_mannager/setup.py | 36 +++ setup.py | 64 +++-- 26 files changed, 593 insertions(+), 89 deletions(-) rename csrcs/fastdeploy/pybind/{main.cc => main.cc.in} (98%) create mode 100644 fastdeploy/c_lib_wrap.py.in create mode 100644 sdk_mannager/fastdeploy/__init__.py create mode 100644 sdk_mannager/fastdeploy/__main__.py create mode 100644 sdk_mannager/fastdeploy/download.py create mode 100644 sdk_mannager/requirements.txt create mode 100644 sdk_mannager/setup.py diff --git a/CMakeLists.txt b/CMakeLists.txt index a030bddd0..11318f470 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -224,7 +224,9 @@ if(ENABLE_TEXT) endif() configure_file(${PROJECT_SOURCE_DIR}/${CSRCS_DIR_NAME}/fastdeploy/core/config.h.in ${PROJECT_SOURCE_DIR}/${CSRCS_DIR_NAME}/fastdeploy/core/config.h) +configure_file(${PROJECT_SOURCE_DIR}/${CSRCS_DIR_NAME}/fastdeploy/pybind/main.cc.in ${PROJECT_SOURCE_DIR}/${CSRCS_DIR_NAME}/fastdeploy/pybind/main.cc) configure_file(${PROJECT_SOURCE_DIR}/FastDeploy.cmake.in ${PROJECT_SOURCE_DIR}/FastDeploy.cmake @ONLY) +configure_file(${PROJECT_SOURCE_DIR}/fastdeploy/c_lib_wrap.py.in ${PROJECT_SOURCE_DIR}/fastdeploy/c_lib_wrap.py) list(REMOVE_ITEM ALL_DEPLOY_SRCS ${DEPLOY_PYBIND_SRCS}) diff --git a/csrcs/fastdeploy/pybind/main.cc b/csrcs/fastdeploy/pybind/main.cc.in similarity index 98% rename from csrcs/fastdeploy/pybind/main.cc rename to csrcs/fastdeploy/pybind/main.cc.in index e0c00c8a0..622c2c82b 100644 --- a/csrcs/fastdeploy/pybind/main.cc +++ b/csrcs/fastdeploy/pybind/main.cc.in @@ -99,7 +99,7 @@ cv::Mat PyArrayToCvMat(pybind11::array& pyarray) { } #endif -PYBIND11_MODULE(fastdeploy_main, m) { +PYBIND11_MODULE(@PY_LIBRARY_NAME@, m) { m.doc() = "Make programer easier to deploy deeplearning model, save time to save " "the world!"; diff --git a/fastdeploy/__init__.py b/fastdeploy/__init__.py index b389669a3..c101eaadb 100644 --- a/fastdeploy/__init__.py +++ b/fastdeploy/__init__.py @@ -16,56 +16,9 @@ import logging import os import sys -try: - import paddle -except: - pass - - -def add_dll_search_dir(dir_path): - os.environ["path"] = dir_path + ";" + os.environ["path"] - sys.path.insert(0, dir_path) - if sys.version_info[:2] >= (3, 8): - os.add_dll_directory(dir_path) - - -if os.name == "nt": - current_path = os.path.abspath(__file__) - dirname = os.path.dirname(current_path) - third_libs_dir = os.path.join(dirname, "libs") - add_dll_search_dir(third_libs_dir) - for root, dirs, filenames in os.walk(third_libs_dir): - for d in dirs: - if d == "lib" or d == "bin": - add_dll_search_dir(os.path.join(dirname, root, d)) - -from .fastdeploy_main import Frontend, Backend, FDDataType, TensorInfo, Device +from .c_lib_wrap import Frontend, Backend, FDDataType, TensorInfo, Device from .runtime import Runtime, RuntimeOption from .model import FastDeployModel -from . import fastdeploy_main as C +from . import c_lib_wrap as C from . import vision from .download import download, download_and_decompress - - -def TensorInfoStr(tensor_info): - message = "TensorInfo(name : '{}', dtype : '{}', shape : '{}')".format( - tensor_info.name, tensor_info.dtype, tensor_info.shape) - return message - - -def RuntimeOptionStr(runtime_option): - attrs = dir(runtime_option) - message = "RuntimeOption(\n" - for attr in attrs: - if attr.startswith("__"): - continue - if hasattr(getattr(runtime_option, attr), "__call__"): - continue - message += " {} : {}\t\n".format(attr, getattr(runtime_option, attr)) - message.strip("\n") - message += ")" - return message - - -C.TensorInfo.__repr__ = TensorInfoStr -C.RuntimeOption.__repr__ = RuntimeOptionStr diff --git a/fastdeploy/c_lib_wrap.py.in b/fastdeploy/c_lib_wrap.py.in new file mode 100644 index 000000000..62c10cfcc --- /dev/null +++ b/fastdeploy/c_lib_wrap.py.in @@ -0,0 +1,59 @@ +# Copyright (c) 2022 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 __future__ import absolute_import +import logging +import os +import sys + +def add_dll_search_dir(dir_path): + os.environ["path"] = dir_path + ";" + os.environ["path"] + sys.path.insert(0, dir_path) + if sys.version_info[:2] >= (3, 8): + os.add_dll_directory(dir_path) + + +if os.name == "nt": + current_path = os.path.abspath(__file__) + dirname = os.path.dirname(current_path) + third_libs_dir = os.path.join(dirname, "libs") + add_dll_search_dir(third_libs_dir) + for root, dirs, filenames in os.walk(third_libs_dir): + for d in dirs: + if d == "lib" or d == "bin": + add_dll_search_dir(os.path.join(dirname, root, d)) + +from .@PY_LIBRARY_NAME@ import * + +def TensorInfoStr(tensor_info): + message = "TensorInfo(name : '{}', dtype : '{}', shape : '{}')".format( + tensor_info.name, tensor_info.dtype, tensor_info.shape) + return message + + +def RuntimeOptionStr(runtime_option): + attrs = dir(runtime_option) + message = "RuntimeOption(\n" + for attr in attrs: + if attr.startswith("__"): + continue + if hasattr(getattr(runtime_option, attr), "__call__"): + continue + message += " {} : {}\t\n".format(attr, getattr(runtime_option, attr)) + message.strip("\n") + message += ")" + return message + + +TensorInfo.__repr__ = TensorInfoStr +RuntimeOption.__repr__ = RuntimeOptionStr diff --git a/fastdeploy/model.py b/fastdeploy/model.py index f0faa1610..dd48ae18f 100644 --- a/fastdeploy/model.py +++ b/fastdeploy/model.py @@ -13,7 +13,7 @@ # limitations under the License. from __future__ import absolute_import import logging -from . import fastdeploy_main as C +from . import c_lib_wrap as C class FastDeployModel: diff --git a/fastdeploy/runtime.py b/fastdeploy/runtime.py index a560f63a2..38c895498 100644 --- a/fastdeploy/runtime.py +++ b/fastdeploy/runtime.py @@ -13,7 +13,7 @@ # limitations under the License. from __future__ import absolute_import import logging -from . import fastdeploy_main as C +from . import c_lib_wrap as C class Runtime: diff --git a/fastdeploy/vision/biubug6/__init__.py b/fastdeploy/vision/biubug6/__init__.py index ca76cfd95..3947f9c3b 100644 --- a/fastdeploy/vision/biubug6/__init__.py +++ b/fastdeploy/vision/biubug6/__init__.py @@ -15,7 +15,7 @@ from __future__ import absolute_import import logging from ... import FastDeployModel, Frontend -from ... import fastdeploy_main as C +from ... import c_lib_wrap as C class RetinaFace(FastDeployModel): diff --git a/fastdeploy/vision/deepcam/__init__.py b/fastdeploy/vision/deepcam/__init__.py index 6b1af4328..2e6e90cc8 100644 --- a/fastdeploy/vision/deepcam/__init__.py +++ b/fastdeploy/vision/deepcam/__init__.py @@ -15,7 +15,7 @@ from __future__ import absolute_import import logging from ... import FastDeployModel, Frontend -from ... import fastdeploy_main as C +from ... import c_lib_wrap as C class YOLOv5Face(FastDeployModel): diff --git a/fastdeploy/vision/deepinsight/__init__.py b/fastdeploy/vision/deepinsight/__init__.py index dbc93ec8e..2025ab33d 100644 --- a/fastdeploy/vision/deepinsight/__init__.py +++ b/fastdeploy/vision/deepinsight/__init__.py @@ -15,7 +15,7 @@ from __future__ import absolute_import import logging from ... import FastDeployModel, Frontend -from ... import fastdeploy_main as C +from ... import c_lib_wrap as C class SCRFD(FastDeployModel): diff --git a/fastdeploy/vision/linzaer/__init__.py b/fastdeploy/vision/linzaer/__init__.py index d31e43682..8c415ff90 100644 --- a/fastdeploy/vision/linzaer/__init__.py +++ b/fastdeploy/vision/linzaer/__init__.py @@ -15,7 +15,7 @@ from __future__ import absolute_import import logging from ... import FastDeployModel, Frontend -from ... import fastdeploy_main as C +from ... import c_lib_wrap as C class UltraFace(FastDeployModel): diff --git a/fastdeploy/vision/megvii/__init__.py b/fastdeploy/vision/megvii/__init__.py index 8f96c9742..76d284cb4 100644 --- a/fastdeploy/vision/megvii/__init__.py +++ b/fastdeploy/vision/megvii/__init__.py @@ -15,7 +15,7 @@ from __future__ import absolute_import import logging from ... import FastDeployModel, Frontend -from ... import fastdeploy_main as C +from ... import c_lib_wrap as C class YOLOX(FastDeployModel): diff --git a/fastdeploy/vision/meituan/__init__.py b/fastdeploy/vision/meituan/__init__.py index 7b6635dd3..80dcc55e3 100644 --- a/fastdeploy/vision/meituan/__init__.py +++ b/fastdeploy/vision/meituan/__init__.py @@ -15,7 +15,7 @@ from __future__ import absolute_import import logging from ... import FastDeployModel, Frontend -from ... import fastdeploy_main as C +from ... import c_lib_wrap as C class YOLOv6(FastDeployModel): diff --git a/fastdeploy/vision/ppcls/__init__.py b/fastdeploy/vision/ppcls/__init__.py index 7eb2bd462..c43a31084 100644 --- a/fastdeploy/vision/ppcls/__init__.py +++ b/fastdeploy/vision/ppcls/__init__.py @@ -15,7 +15,7 @@ from __future__ import absolute_import import logging from ... import FastDeployModel, Frontend -from ... import fastdeploy_main as C +from ... import c_lib_wrap as C class Model(FastDeployModel): diff --git a/fastdeploy/vision/ppdet/__init__.py b/fastdeploy/vision/ppdet/__init__.py index 08d39a36b..6d3738412 100644 --- a/fastdeploy/vision/ppdet/__init__.py +++ b/fastdeploy/vision/ppdet/__init__.py @@ -15,7 +15,7 @@ from __future__ import absolute_import import logging from ... import FastDeployModel, Frontend -from ... import fastdeploy_main as C +from ... import c_lib_wrap as C class PPYOLOE(FastDeployModel): diff --git a/fastdeploy/vision/ppogg/__init__.py b/fastdeploy/vision/ppogg/__init__.py index 3acd1edb2..a056148fe 100644 --- a/fastdeploy/vision/ppogg/__init__.py +++ b/fastdeploy/vision/ppogg/__init__.py @@ -15,7 +15,7 @@ from __future__ import absolute_import import logging from ... import FastDeployModel, Frontend -from ... import fastdeploy_main as C +from ... import c_lib_wrap as C class YOLOv5Lite(FastDeployModel): diff --git a/fastdeploy/vision/ppseg/__init__.py b/fastdeploy/vision/ppseg/__init__.py index dbc826722..1cb146c74 100644 --- a/fastdeploy/vision/ppseg/__init__.py +++ b/fastdeploy/vision/ppseg/__init__.py @@ -15,7 +15,7 @@ from __future__ import absolute_import import logging from ... import FastDeployModel, Frontend -from ... import fastdeploy_main as C +from ... import c_lib_wrap as C class Model(FastDeployModel): diff --git a/fastdeploy/vision/rangilyu/__init__.py b/fastdeploy/vision/rangilyu/__init__.py index f2e8ace9f..e4c12b89f 100644 --- a/fastdeploy/vision/rangilyu/__init__.py +++ b/fastdeploy/vision/rangilyu/__init__.py @@ -15,7 +15,7 @@ from __future__ import absolute_import import logging from ... import FastDeployModel, Frontend -from ... import fastdeploy_main as C +from ... import c_lib_wrap as C class NanoDetPlus(FastDeployModel): diff --git a/fastdeploy/vision/ultralytics/__init__.py b/fastdeploy/vision/ultralytics/__init__.py index 4dcd0d6d4..a971e202b 100644 --- a/fastdeploy/vision/ultralytics/__init__.py +++ b/fastdeploy/vision/ultralytics/__init__.py @@ -15,7 +15,7 @@ from __future__ import absolute_import import logging from ... import FastDeployModel, Frontend -from ... import fastdeploy_main as C +from ... import c_lib_wrap as C class YOLOv5(FastDeployModel): diff --git a/fastdeploy/vision/visualize/__init__.py b/fastdeploy/vision/visualize/__init__.py index ea836b68e..9fac0ab9a 100644 --- a/fastdeploy/vision/visualize/__init__.py +++ b/fastdeploy/vision/visualize/__init__.py @@ -14,7 +14,7 @@ from __future__ import absolute_import import logging -from ... import fastdeploy_main as C +from ... import c_lib_wrap as C def vis_detection(im_data, det_result, line_size=1, font_size=0.5): diff --git a/fastdeploy/vision/wongkinyiu/__init__.py b/fastdeploy/vision/wongkinyiu/__init__.py index c1a3d37f7..1e0a3def7 100644 --- a/fastdeploy/vision/wongkinyiu/__init__.py +++ b/fastdeploy/vision/wongkinyiu/__init__.py @@ -15,7 +15,7 @@ from __future__ import absolute_import import logging from ... import FastDeployModel, Frontend -from ... import fastdeploy_main as C +from ... import c_lib_wrap as C class YOLOv7(FastDeployModel): diff --git a/sdk_mannager/fastdeploy/__init__.py b/sdk_mannager/fastdeploy/__init__.py new file mode 100644 index 000000000..ff1cb0c72 --- /dev/null +++ b/sdk_mannager/fastdeploy/__init__.py @@ -0,0 +1,230 @@ +# Copyright (c) 2022 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 __future__ import absolute_import +from six import text_type as _text_type +import logging +import argparse + +# Since the source code is not fully open sourced, +# currently we will provide the prebuilt library +# and demo codes +import os + +__version__ = "0.1.1" + + +def is_installed(package_name): + import pkg_resources + try: + pkg_resources.get_distribution(package_name) + except pkg_resources.DistributionNotFound: + return False + return True + + +def get_version(package_name): + if not is_installed(package_name): + raise Exception("{} is not installed.".format(package_name)) + major = pkg_resources.get_distribution(package).parsed_version.major + micro = pkg_resources.get_distribution(package).parsed_version.micro + minor = pkg_resources.get_distribution(package).parsed_version.minor + return major, micro, minor + + +def parse_arguments(): + parser = argparse.ArgumentParser() + parser.add_argument( + '--model', + type=_text_type, + default=None, + help='Name of model, which can be listed by --list_models') + parser.add_argument( + '--platform', + type=_text_type, + default=None, + help='Define platform, supports Windows/Linux/Android/iOS.') + parser.add_argument( + '--soc', + type=_text_type, + default=None, + help='Define soc for the platform, supports x86/x86-NVIDIA_GPU/ARM/jetson.' + ) + parser.add_argument( + '--save_dir', + type=_text_type, + default=".", + help='Path to download and extract deployment SDK.') + parser.add_argument( + '--list_models', + required=False, + action="store_true", + default=False, + help='List all the supported models.') + parser.add_argument( + '--download_sdk', + required=False, + action="store_true", + default=False, + help='List all the supported models.') + + return parser.parse_args() + + +def read_sources(): + from .download import download, download_and_decompress + user_dir = os.path.expanduser('~') + print("Updating the newest sdk information...") + source_cfgs = "https://bj.bcebos.com/paddlehub/fastdeploy/fastdeploy_newest_sources.cfg.1" + if os.path.exists( + os.path.join(user_dir, "fastdeploy_newest_sources.cfg.1")): + os.remove(os.path.join(user_dir, "fastdeploy_newest_sources.cfg.1")) + download(source_cfgs, user_dir) + categories = dict() + res = dict() + with open(os.path.join(user_dir, "fastdeploy_newest_sources.cfg.1")) as f: + for line in f: + if line.strip().startswith("#"): + continue + if line.strip() == "": + continue + category, model, plat, soc, url = line.strip().split('\t') + if category not in categories: + categories[category] = set() + categories[category].add(model) + if model not in res: + res[model] = dict() + if plat not in res[model]: + res[model][plat] = dict() + if soc not in res[model][plat]: + res[model][plat][soc] = dict() + res[model][plat][soc] = url + return categories, res + + +def main(): + from .download import download, download_and_decompress + + args = parse_arguments() + + if not args.list_models and not args.download_sdk: + print( + "Please use flag --list_models to show all the supported models, or use flag --download_sdk to download the specify SDK to deploy you model." + ) + return + + categories, all_sources = read_sources() + all_models = list(all_sources.keys()) + all_models.sort() + + if args.list_models: + print("Currently, FastDeploy supports {} models, list as below,\n". + format(len(all_models))) + + for k, v in categories.items(): + print("\nModel Category: {}".format(k)) + print("_" * 100) + models = list(categories[k]) + models.sort() + i = 0 + while i < len(models): + if i == len(models) - 1: + print(models[i].center(30)) + i += 1 + elif i == len(models) - 2: + print(models[i].center(30), models[i + 1].center(30)) + i += 2 + else: + print(models[i].center(30), models[i + 1].center(30), + models[i + 2].center(30)) + i += 3 + return + + if not os.path.exists(args.save_dir): + print("The specified save_dir: {} is not exist.".format(args.save_dir)) + return + + if args.model is None or args.model == "": + print( + "Please define --model to choose which kind of model to deploy, use --list_models to show all the supported models." + ) + return + + if args.model not in all_sources: + print( + "{} is not supported, use --list_models to list all the models FastDeploy supported.". + format(args.model)) + return + + if args.platform is None or args.platform == "": + print( + "Please define --platform to choose which platform to deploy, supports windows/linux/android/ios." + ) + return + + if args.platform not in all_sources[args.model]: + print( + "The model:{} only supports platform of {}, {} is not supported now.". + format(args.model, + list(all_sources[args.model].keys()), args.platform)) + return + + if args.soc is None or args.soc == "": + print( + "Please define --soc to choose which hardware to deploy, for model:{} and platform:{}, the available socs are {}.". + format(args.model, args.platform, + list(all_sources[args.model][args.platform].keys()))) + return + + if args.soc not in all_sources[args.model][args.platform]: + print( + "The model:{} in platform:{} only supports soc of {}, {} is not supported now.". + format(args.model, args.platform, + list(all_sources[args.model][args.platform].keys()), + args.soc)) + return + + print("\nDownloading SDK:", + all_sources[args.model][args.platform][args.soc]) + + save_dir = args.save_dir + sdk_name = os.path.split(all_sources[args.model][args.platform][args.soc])[ + -1].strip() + if all_sources[args.model][args.platform][args.soc].count(".zip") > 0: + sdk_name = os.path.split(all_sources[args.model][args.platform][ + args.soc])[-1].strip().split(".zip")[0] + new_save_dir = os.path.join(args.save_dir, sdk_name) + if not os.path.exists(new_save_dir): + os.mkdir(new_save_dir) + save_dir = new_save_dir + download_and_decompress( + all_sources[args.model][args.platform][args.soc], + new_save_dir, + rename=sdk_name + ".zip") + os.remove(os.path.join(new_save_dir, sdk_name + ".zip")) + print("Done. All the files of SDK have been extracted in {}.".format( + new_save_dir)) + + +if __name__ == "__main__": + main() + +if is_installed('cpu_fastdeploy'): + from cpu_fastdeploy import * +elif is_installed('gpu_fastdeploy'): + from gpu_fastdeploy import * +else: + print( + "[INFO] Didn't install cpu/gpu sdk in your environment now, refer https://github.com/PaddlePaddle/FastDeploy/blob/release/0.2.0/docs/server_install.md for more details." + ) diff --git a/sdk_mannager/fastdeploy/__main__.py b/sdk_mannager/fastdeploy/__main__.py new file mode 100644 index 000000000..6abf5cf8f --- /dev/null +++ b/sdk_mannager/fastdeploy/__main__.py @@ -0,0 +1,18 @@ +# Copyright (c) 2022 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. + +import fastdeploy + +if __name__ == "__main__": + fastdeploy.main() diff --git a/sdk_mannager/fastdeploy/download.py b/sdk_mannager/fastdeploy/download.py new file mode 100644 index 000000000..3b5e92bf3 --- /dev/null +++ b/sdk_mannager/fastdeploy/download.py @@ -0,0 +1,186 @@ +# Copyright (c) 2021 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. + +import os +import os.path as osp +import shutil +import requests +import time +import zipfile +import hashlib +import tqdm +import logging + +DOWNLOAD_RETRY_LIMIT = 3 + + +def md5check(fullname, md5sum=None): + if md5sum is None: + return True + + logging.info("File {} md5 checking...".format(fullname)) + md5 = hashlib.md5() + with open(fullname, 'rb') as f: + for chunk in iter(lambda: f.read(4096), b""): + md5.update(chunk) + calc_md5sum = md5.hexdigest() + + if calc_md5sum != md5sum: + logging.info("File {} md5 check failed, {}(calc) != " + "{}(base)".format(fullname, calc_md5sum, md5sum)) + return False + return True + + +def move_and_merge_tree(src, dst): + """ + Move src directory to dst, if dst is already exists, + merge src to dst + """ + if not osp.exists(dst): + shutil.move(src, dst) + else: + if not osp.isdir(src): + shutil.move(src, dst) + return + for fp in os.listdir(src): + src_fp = osp.join(src, fp) + dst_fp = osp.join(dst, fp) + if osp.isdir(src_fp): + if osp.isdir(dst_fp): + move_and_merge_tree(src_fp, dst_fp) + else: + shutil.move(src_fp, dst_fp) + elif osp.isfile(src_fp) and \ + not osp.isfile(dst_fp): + shutil.move(src_fp, dst_fp) + + +def download(url, path, rename=None, md5sum=None, show_progress=False): + """ + Download from url, save to path. + url (str): download url + path (str): download to given path + """ + if not osp.exists(path): + os.makedirs(path) + + fname = osp.split(url)[-1] + fullname = osp.join(path, fname) + if rename is not None: + fullname = osp.join(path, rename) + retry_cnt = 0 + while not (osp.exists(fullname) and md5check(fullname, md5sum)): + if retry_cnt < DOWNLOAD_RETRY_LIMIT: + retry_cnt += 1 + else: + logging.debug("{} download failed.".format(fname)) + raise RuntimeError("Download from {} failed. " + "Retry limit reached".format(url)) + + logging.info("Downloading {} from {}".format(fname, url)) + + req = requests.get(url, stream=True) + if req.status_code != 200: + raise RuntimeError("Downloading from {} failed with code " + "{}!".format(url, req.status_code)) + + # For protecting download interupted, download to + # tmp_fullname firstly, move tmp_fullname to fullname + # after download finished + tmp_fullname = fullname + "_tmp" + total_size = req.headers.get('content-length') + with open(tmp_fullname, 'wb') as f: + if total_size and show_progress: + for chunk in tqdm.tqdm( + req.iter_content(chunk_size=1024), + total=(int(total_size) + 1023) // 1024, + unit='KB'): + f.write(chunk) + else: + for chunk in req.iter_content(chunk_size=1024): + if chunk: + f.write(chunk) + shutil.move(tmp_fullname, fullname) + logging.debug("{} download completed.".format(fname)) + + return fullname + + +def decompress(fname): + """ + Decompress for zip and tar file + """ + logging.info("Decompressing {}...".format(fname)) + + # For protecting decompressing interupted, + # decompress to fpath_tmp directory firstly, if decompress + # successed, move decompress files to fpath and delete + # fpath_tmp and remove download compress file. + fpath = osp.split(fname)[0] + fpath_tmp = osp.join(fpath, 'tmp') + if osp.isdir(fpath_tmp): + shutil.rmtree(fpath_tmp) + os.makedirs(fpath_tmp) + + if fname.find('.tar') >= 0 or fname.find('.tgz') >= 0: + with tarfile.open(fname) as tf: + tf.extractall(path=fpath_tmp) + elif fname.find('.zip') >= 0: + with zipfile.ZipFile(fname) as zf: + zf.extractall(path=fpath_tmp) + else: + raise TypeError("Unsupport compress file type {}".format(fname)) + + for f in os.listdir(fpath_tmp): + src_dir = osp.join(fpath_tmp, f) + dst_dir = osp.join(fpath, f) + move_and_merge_tree(src_dir, dst_dir) + + shutil.rmtree(fpath_tmp) + logging.debug("{} decompressed.".format(fname)) + return dst_dir + + +def url2dir(url, path, rename=None): + full_name = download(url, path, rename, show_progress=True) + print("SDK is donwloaded, now extracting...") + if url.count(".tgz") > 0 or url.count(".tar") > 0 or url.count("zip") > 0: + return decompress(full_name) + + +def download_and_decompress(url, path='.', rename=None): + fname = osp.split(url)[-1] + fullname = osp.join(path, fname) + # if url.endswith(('tgz', 'tar.gz', 'tar', 'zip')): + # fullname = osp.join(path, fname.split('.')[0]) + nranks = 0 + if nranks <= 1: + dst_dir = url2dir(url, path, rename) + if dst_dir is not None: + fullname = dst_dir + else: + lock_path = fullname + '.lock' + if not os.path.exists(fullname): + with open(lock_path, 'w'): + os.utime(lock_path, None) + if local_rank == 0: + dst_dir = url2dir(url, path, rename) + if dst_dir is not None: + fullname = dst_dir + os.remove(lock_path) + else: + while os.path.exists(lock_path): + time.sleep(1) + return diff --git a/sdk_mannager/requirements.txt b/sdk_mannager/requirements.txt new file mode 100644 index 000000000..5f64a9a19 --- /dev/null +++ b/sdk_mannager/requirements.txt @@ -0,0 +1,2 @@ +tqdm +six diff --git a/sdk_mannager/setup.py b/sdk_mannager/setup.py new file mode 100644 index 000000000..787071a1b --- /dev/null +++ b/sdk_mannager/setup.py @@ -0,0 +1,36 @@ +import setuptools +import fastdeploy +import io +import os + +with open("requirements.txt") as fin: + REQUIRED_PACKAGES = fin.read() + + +def read(*names, **kwargs): + with io.open( + os.path.join(os.path.dirname(__file__), *names), + encoding=kwargs.get("encoding", "utf8")) as fp: + return fp.read() + + +setuptools.setup( + name="fastdeploy-python", + version=fastdeploy.__version__, + author="FastDeploy", + author_email="fastdeploy@baidu.com", + description="FastDeploy is a toolkit to deploy deeplearning models.", + long_description=read("../README.md"), + long_description_content_type="text/markdown", + url="https://github.com/PaddlePaddle/FastDeploy", + packages=setuptools.find_packages(), + install_requires=REQUIRED_PACKAGES, + classifiers=[ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: Apache Software License", + "Operating System :: OS Independent", + ], + license='Apache 2.0', + entry_points={ + 'console_scripts': ['fastdeploy=fastdeploy.__init__:main', ] + }) diff --git a/setup.py b/setup.py index 15f5fc29d..7043ed8dd 100644 --- a/setup.py +++ b/setup.py @@ -17,6 +17,17 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function from __future__ import unicode_literals +import shutil +import os + +PACKAGE_NAME = os.getenv("PACKAGE_NAME", "fastdeploy") +assert PACKAGE_NAME in [ + "cpu_fastdeploy", "gpu_fastdeploy", "fastdeploy" +], "Only support PACKAGE_NAME set to ['cpu_fastdeploy', 'gpu_fastdeploy', 'fastdeploy'] now." +if PACKAGE_NAME != "fastdeploy": + if os.path.exists(PACKAGE_NAME): + shutil.rmtree(PACKAGE_NAME) + shutil.copytree("fastdeploy", PACKAGE_NAME) from distutils.spawn import find_executable from distutils import sysconfig, log @@ -28,7 +39,6 @@ import setuptools.command.build_ext from collections import namedtuple from contextlib import contextmanager import glob -import os import shlex import subprocess import sys @@ -39,7 +49,6 @@ import multiprocessing with open("requirements.txt") as fin: REQUIRED_PACKAGES = fin.read() -PACKAGE_NAME = "fastdeploy" setup_configs = dict() setup_configs["ENABLE_PADDLE_FRONTEND"] = os.getenv("ENABLE_PADDLE_FRONTEND", "ON") @@ -53,11 +62,14 @@ setup_configs["WITH_GPU"] = os.getenv("WITH_GPU", "OFF") setup_configs["TRT_DIRECTORY"] = os.getenv("TRT_DIRECTORY", "UNDEFINED") setup_configs["CUDA_DIRECTORY"] = os.getenv("CUDA_DIRECTORY", "/usr/local/cuda") +setup_configs["LIBRARY_NAME"] = PACKAGE_NAME +setup_configs["PY_LIBRARY_NAME"] = PACKAGE_NAME + "_main" + if os.getenv("CMAKE_CXX_COMPILER", None) is not None: setup_configs["CMAKE_CXX_COMPILER"] = os.getenv("CMAKE_CXX_COMPILER") TOP_DIR = os.path.realpath(os.path.dirname(__file__)) -SRC_DIR = os.path.join(TOP_DIR, "fastdeploy") +SRC_DIR = os.path.join(TOP_DIR, PACKAGE_NAME) CMAKE_BUILD_DIR = os.path.join(TOP_DIR, '.setuptools-cmake-build') WINDOWS = (os.name == 'nt') @@ -237,8 +249,8 @@ class build_py(setuptools.command.build_py.build_py): self.run_command('cmake_build') generated_python_files = \ - glob.glob(os.path.join(CMAKE_BUILD_DIR, 'fastdeploy', '*.py')) + \ - glob.glob(os.path.join(CMAKE_BUILD_DIR, 'fastdeploy', '*.pyi')) + glob.glob(os.path.join(CMAKE_BUILD_DIR, PACKAGE_NAME, '*.py')) + \ + glob.glob(os.path.join(CMAKE_BUILD_DIR, PACKAGE_NAME, '*.pyi')) for src in generated_python_files: dst = os.path.join(TOP_DIR, os.path.relpath(src, CMAKE_BUILD_DIR)) @@ -273,7 +285,7 @@ class build_ext(setuptools.command.build_ext.build_ext): lib_path = release_lib_dir src = os.path.join(lib_path, filename) dst = os.path.join( - os.path.realpath(self.build_lib), "fastdeploy", filename) + os.path.realpath(self.build_lib), PACKAGE_NAME, filename) self.copy_file(src, dst) @@ -305,7 +317,8 @@ cmdclass = { ext_modules = [ setuptools.Extension( - name=str(PACKAGE_NAME + '.fastdeploy_main'), sources=[]), + name=str(PACKAGE_NAME + '.' + setup_configs["PY_LIBRARY_NAME"]), + sources=[]), ] ################################################################################ @@ -313,7 +326,10 @@ ext_modules = [ ################################################################################ # no need to do fancy stuff so far -packages = setuptools.find_packages() +if PACKAGE_NAME != "fastdeploy": + packages = setuptools.find_packages(exclude=['fastdeploy*']) +else: + packages = setuptools.find_packages() ################################################################################ # Test @@ -335,8 +351,8 @@ if sys.argv[1] == "install" or sys.argv[1] == "bdist_wheel": sys.exit(0) import shutil - shutil.copy("ThirdPartyNotices.txt", "fastdeploy") - shutil.copy("LICENSE", "fastdeploy") + shutil.copy("ThirdPartyNotices.txt", PACKAGE_NAME) + shutil.copy("LICENSE", PACKAGE_NAME) depend_libs = list() # copy fastdeploy library @@ -344,10 +360,11 @@ if sys.argv[1] == "install" or sys.argv[1] == "bdist_wheel": for f in os.listdir(".setuptools-cmake-build"): if not os.path.isfile(os.path.join(".setuptools-cmake-build", f)): continue - if f.count("fastdeploy") > 0: + if f.count(PACKAGE_NAME) > 0: shutil.copy( - os.path.join(".setuptools-cmake-build", f), "fastdeploy/libs") - if f.count("fastdeploy_main.cpython-"): + os.path.join(".setuptools-cmake-build", f), + os.path.join(PACKAGE_NAME, "libs")) + if f.count(".cpython-") > 0: pybind_so_file = os.path.join(".setuptools-cmake-build", f) if not os.path.exists(".setuptools-cmake-build/third_libs/install"): @@ -355,11 +372,11 @@ if sys.argv[1] == "install" or sys.argv[1] == "bdist_wheel": "Cannot find directory third_libs/install in .setuptools-cmake-build." ) - if os.path.exists("fastdeploy/libs/third_libs"): - shutil.rmtree("fastdeploy/libs/third_libs") + if os.path.exists(os.path.join(PACKAGE_NAME, "libs/third_libs")): + shutil.rmtree(os.path.join(PACKAGE_NAME, "libs/third_libs")) shutil.copytree( ".setuptools-cmake-build/third_libs/install", - "fastdeploy/libs/third_libs", + os.path.join(PACKAGE_NAME, "libs/third_libs"), symlinks=True) third_party_path = os.path.join(".setuptools-cmake-build", "third_party") @@ -372,12 +389,12 @@ if sys.argv[1] == "install" or sys.argv[1] == "bdist_wheel": release_dir = os.path.join(lib_dir_name, f1) if f1 == "Release" and not os.path.isfile(release_dir): if os.path.exists( - os.path.join("fastdeploy/libs/third_libs", f)): + os.path.join(PACKAGE_NAME, "libs/third_libs", f)): shutil.rmtree( - os.path.join("fastdeploy/libs/third_libs", f)) + os.path.join(PACKAGE_NAME, "libs/third_libs", f)) shutil.copytree(release_dir, - os.path.join("fastdeploy/libs/third_libs", - f, "lib")) + os.path.join(PACKAGE_NAME, + "libs/third_libs", f, "lib")) if platform.system().lower() == "windows": release_dir = os.path.join(".setuptools-cmake-build", "Release") @@ -387,7 +404,7 @@ if sys.argv[1] == "install" or sys.argv[1] == "bdist_wheel": continue if filename.endswith(".pyd"): continue - shutil.copy(filename, "fastdeploy/libs") + shutil.copy(filename, os.path.join(PACKAGE_NAME, "libs")) if platform.system().lower() == "linux": rpaths = ["$ORIGIN:$ORIGIN/libs"] @@ -445,9 +462,10 @@ if sys.argv[1] == "install" or sys.argv[1] == "bdist_wheel": command) == 0, "command execute failed! command: {}".format( command) - all_files = get_all_files("fastdeploy/libs") + all_files = get_all_files(os.path.join(PACKAGE_NAME, "libs")) for f in all_files: - package_data[PACKAGE_NAME].append(os.path.relpath(f, "fastdeploy")) + package_data[PACKAGE_NAME].append(os.path.relpath(f, PACKAGE_NAME)) + setuptools.setup( name=PACKAGE_NAME, version=VersionInfo.version,