提交 260afdb4 编写于 作者: M MRXLT

fix conflict

...@@ -65,8 +65,8 @@ endif() ...@@ -65,8 +65,8 @@ endif()
if (NOT CLIENT_ONLY) if (NOT CLIENT_ONLY)
include(external/jsoncpp) include(external/jsoncpp)
include(external/rocksdb) include(external/rocksdb)
include(external/gtest)
endif() endif()
#include(external/gtest)
include(external/snappy) include(external/snappy)
include(external/leveldb) include(external/leveldb)
......
...@@ -5,7 +5,7 @@ An easy-to-use Machine Learning Model Inference Service Deployment Tool ...@@ -5,7 +5,7 @@ An easy-to-use Machine Learning Model Inference Service Deployment Tool
[![Issues](https://img.shields.io/github/issues/PaddlePaddle/Serving)](Issues) [![Issues](https://img.shields.io/github/issues/PaddlePaddle/Serving)](Issues)
[![License](https://img.shields.io/github/license/PaddlePaddle/Serving)](LICENSE) [![License](https://img.shields.io/github/license/PaddlePaddle/Serving)](LICENSE)
[中文](./README_CN.md) [中文](./doc/README_CN.md)
Paddle Serving is the online inference service framework of [Paddle](https://github.com/PaddlePaddle/Paddle) that can help developers easily deploy a deep learning model service on server side and send request from mobile devices, edge devices as well as data centers. Currently, Paddle Serving supports the deep learning models produced by Paddle althought it can be very easy to support other deep learning framework's model inference. Paddle Serving is designed oriented from industrial practice. For example, multiple models management for online service, double buffers model loading, models online A/B testing are supported. Highly concurrent [Baidu-rpc](https://github.com/apache/incubator-brpc) is used as the underlying communication library which is also from industry practice. Paddle Serving provides user-friendly API that can integrate with Paddle training code seamlessly, and users can finish model training and model serving in an end-to-end fasion. Paddle Serving is the online inference service framework of [Paddle](https://github.com/PaddlePaddle/Paddle) that can help developers easily deploy a deep learning model service on server side and send request from mobile devices, edge devices as well as data centers. Currently, Paddle Serving supports the deep learning models produced by Paddle althought it can be very easy to support other deep learning framework's model inference. Paddle Serving is designed oriented from industrial practice. For example, multiple models management for online service, double buffers model loading, models online A/B testing are supported. Highly concurrent [Baidu-rpc](https://github.com/apache/incubator-brpc) is used as the underlying communication library which is also from industry practice. Paddle Serving provides user-friendly API that can integrate with Paddle training code seamlessly, and users can finish model training and model serving in an end-to-end fasion.
...@@ -22,6 +22,7 @@ pip install paddle-serving-client ...@@ -22,6 +22,7 @@ pip install paddle-serving-client
pip install paddle-serving-server pip install paddle-serving-server
``` ```
### Training Scripts ### Training Scripts
``` python ``` python
...@@ -121,7 +122,7 @@ for data in test_reader(): ...@@ -121,7 +122,7 @@ for data in test_reader():
### Advanced features and development ### Advanced features and development
[Compile from source code(Chinese)](doc/INSTALL.md) [Compile from source code(Chinese)](doc/COMPILE.md)
## Contribution ## Contribution
......
...@@ -28,7 +28,7 @@ ExternalProject_Add( ...@@ -28,7 +28,7 @@ ExternalProject_Add(
GIT_TAG master GIT_TAG master
UPDATE_COMMAND "" UPDATE_COMMAND ""
CONFIGURE_COMMAND "" CONFIGURE_COMMAND ""
BUILD_COMMAND CXXFLAGS=-fPIC && mkdir build && cd build && cmake .. && make -j ${NUM_OF_PROCESSOR} gtest BUILD_COMMAND CXXFLAGS=-fPIC && mkdir -p build && cd build && cmake .. && make -j ${NUM_OF_PROCESSOR} gtest
INSTALL_COMMAND mkdir -p ${GTEST_INSTALL_DIR}/lib/ INSTALL_COMMAND mkdir -p ${GTEST_INSTALL_DIR}/lib/
&& cp ${GTEST_SOURCES_DIR}/src/extern_gtest/build/lib/libgtest.a ${GTEST_LIBRARIES} && cp ${GTEST_SOURCES_DIR}/src/extern_gtest/build/lib/libgtest.a ${GTEST_LIBRARIES}
&& cp -r ${GTEST_SOURCES_DIR}/src/extern_gtest/googletest/include ${GTEST_INSTALL_DIR}/ && cp -r ${GTEST_SOURCES_DIR}/src/extern_gtest/googletest/include ${GTEST_INSTALL_DIR}/
...@@ -41,4 +41,3 @@ ADD_LIBRARY(gtest STATIC IMPORTED GLOBAL) ...@@ -41,4 +41,3 @@ ADD_LIBRARY(gtest STATIC IMPORTED GLOBAL)
SET_PROPERTY(TARGET gtest PROPERTY IMPORTED_LOCATION ${GTEST_LIBRARIES}) SET_PROPERTY(TARGET gtest PROPERTY IMPORTED_LOCATION ${GTEST_LIBRARIES})
LIST(APPEND external_project_dependencies gtest) LIST(APPEND external_project_dependencies gtest)
...@@ -67,10 +67,10 @@ endif() ...@@ -67,10 +67,10 @@ endif()
target_link_libraries(cube brpc ${DYNAMIC_LIB} -lpthread -ldl -lz) target_link_libraries(cube brpc ${DYNAMIC_LIB} -lpthread -ldl -lz)
add_executable(cube_test ${SRC_LIST} test/cube_test.cpp #add_executable(cube_test ${SRC_LIST} test/cube_test.cpp
${PROTO_SRC} ${PROTO_HEADER}) # ${PROTO_SRC} ${PROTO_HEADER})
target_link_libraries(cube_test brpc ${DYNAMIC_LIB} gtest -lpthread -ldl -lz) #target_link_libraries(cube_test brpc ${DYNAMIC_LIB} gtest -lpthread -ldl -lz)
# install # install
install(TARGETS cube install(TARGETS cube
......
make: *** No targets specified and no makefile found. Stop.
...@@ -36,8 +36,9 @@ using baidu::paddle_serving::predictor::InferManager; ...@@ -36,8 +36,9 @@ using baidu::paddle_serving::predictor::InferManager;
using baidu::paddle_serving::predictor::PaddleGeneralModelConfig; using baidu::paddle_serving::predictor::PaddleGeneralModelConfig;
int GeneralInferOp::inference() { int GeneralInferOp::inference() {
VLOG(2) << "Going to run inference";
const GeneralBlob *input_blob = get_depend_argument<GeneralBlob>(pre_name()); const GeneralBlob *input_blob = get_depend_argument<GeneralBlob>(pre_name());
VLOG(2) << "Get precedent op name: " << pre_name();
GeneralBlob *output_blob = mutable_data<GeneralBlob>(); GeneralBlob *output_blob = mutable_data<GeneralBlob>();
if (!input_blob) { if (!input_blob) {
...@@ -48,6 +49,8 @@ int GeneralInferOp::inference() { ...@@ -48,6 +49,8 @@ int GeneralInferOp::inference() {
const TensorVector *in = &input_blob->tensor_vector; const TensorVector *in = &input_blob->tensor_vector;
TensorVector *out = &output_blob->tensor_vector; TensorVector *out = &output_blob->tensor_vector;
int batch_size = input_blob->GetBatchSize(); int batch_size = input_blob->GetBatchSize();
VLOG(2) << "input batch size: " << batch_size;
output_blob->SetBatchSize(batch_size); output_blob->SetBatchSize(batch_size);
VLOG(2) << "infer batch size: " << batch_size; VLOG(2) << "infer batch size: " << batch_size;
......
...@@ -45,7 +45,9 @@ int GeneralTextReaderOp::inference() { ...@@ -45,7 +45,9 @@ int GeneralTextReaderOp::inference() {
std::vector<int64_t> capacity; std::vector<int64_t> capacity;
GeneralBlob *res = mutable_data<GeneralBlob>(); GeneralBlob *res = mutable_data<GeneralBlob>();
TensorVector *in = &res->tensor_vector; TensorVector *out = &res->tensor_vector;
res->SetBatchSize(batch_size);
if (!res) { if (!res) {
LOG(ERROR) << "Failed get op tls reader object output"; LOG(ERROR) << "Failed get op tls reader object output";
...@@ -103,23 +105,23 @@ int GeneralTextReaderOp::inference() { ...@@ -103,23 +105,23 @@ int GeneralTextReaderOp::inference() {
VLOG(2) << "var[" << i << "] is tensor, capacity: " << capacity[i]; VLOG(2) << "var[" << i << "] is tensor, capacity: " << capacity[i];
} }
lod_tensor.name = model_config->_feed_name[i]; lod_tensor.name = model_config->_feed_name[i];
in->push_back(lod_tensor); out->push_back(lod_tensor);
} }
for (int i = 0; i < var_num; ++i) { for (int i = 0; i < var_num; ++i) {
if (in->at(i).lod.size() == 1) { if (out->at(i).lod.size() == 1) {
for (int j = 0; j < batch_size; ++j) { for (int j = 0; j < batch_size; ++j) {
const Tensor &tensor = req->insts(j).tensor_array(i); const Tensor &tensor = req->insts(j).tensor_array(i);
int data_len = tensor.int_data_size(); int data_len = tensor.int_data_size();
int cur_len = in->at(i).lod[0].back(); int cur_len = out->at(i).lod[0].back();
in->at(i).lod[0].push_back(cur_len + data_len); out->at(i).lod[0].push_back(cur_len + data_len);
} }
in->at(i).data.Resize(in->at(i).lod[0].back() * elem_size[i]); out->at(i).data.Resize(out->at(i).lod[0].back() * elem_size[i]);
in->at(i).shape = {in->at(i).lod[0].back(), 1}; out->at(i).shape = {out->at(i).lod[0].back(), 1};
VLOG(2) << "var[" << i VLOG(2) << "var[" << i
<< "] is lod_tensor and len=" << in->at(i).lod[0].back(); << "] is lod_tensor and len=" << out->at(i).lod[0].back();
} else { } else {
in->at(i).data.Resize(batch_size * capacity[i] * elem_size[i]); out->at(i).data.Resize(batch_size * capacity[i] * elem_size[i]);
VLOG(2) << "var[" << i VLOG(2) << "var[" << i
<< "] is tensor and capacity=" << batch_size * capacity[i]; << "] is tensor and capacity=" << batch_size * capacity[i];
} }
...@@ -127,7 +129,7 @@ int GeneralTextReaderOp::inference() { ...@@ -127,7 +129,7 @@ int GeneralTextReaderOp::inference() {
for (int i = 0; i < var_num; ++i) { for (int i = 0; i < var_num; ++i) {
if (elem_type[i] == 0) { if (elem_type[i] == 0) {
int64_t *dst_ptr = static_cast<int64_t *>(in->at(i).data.data()); int64_t *dst_ptr = static_cast<int64_t *>(out->at(i).data.data());
int offset = 0; int offset = 0;
for (int j = 0; j < batch_size; ++j) { for (int j = 0; j < batch_size; ++j) {
for (int k = 0; for (int k = 0;
...@@ -136,14 +138,14 @@ int GeneralTextReaderOp::inference() { ...@@ -136,14 +138,14 @@ int GeneralTextReaderOp::inference() {
dst_ptr[offset + k] = dst_ptr[offset + k] =
req->insts(j).tensor_array(i).int_data(k); req->insts(j).tensor_array(i).int_data(k);
} }
if (in->at(i).lod.size() == 1) { if (out->at(i).lod.size() == 1) {
offset = in->at(i).lod[0][j + 1]; offset = out->at(i).lod[0][j + 1];
} else { } else {
offset += capacity[i]; offset += capacity[i];
} }
} }
} else { } else {
float *dst_ptr = static_cast<float *>(in->at(i).data.data()); float *dst_ptr = static_cast<float *>(out->at(i).data.data());
int offset = 0; int offset = 0;
for (int j = 0; j < batch_size; ++j) { for (int j = 0; j < batch_size; ++j) {
for (int k = 0; for (int k = 0;
...@@ -152,8 +154,8 @@ int GeneralTextReaderOp::inference() { ...@@ -152,8 +154,8 @@ int GeneralTextReaderOp::inference() {
dst_ptr[offset + k] = dst_ptr[offset + k] =
req->insts(j).tensor_array(i).int_data(k); req->insts(j).tensor_array(i).int_data(k);
} }
if (in->at(i).lod.size() == 1) { if (out->at(i).lod.size() == 1) {
offset = in->at(i).lod[0][j + 1]; offset = out->at(i).lod[0][j + 1];
} else { } else {
offset += capacity[i]; offset += capacity[i];
} }
...@@ -162,6 +164,7 @@ int GeneralTextReaderOp::inference() { ...@@ -162,6 +164,7 @@ int GeneralTextReaderOp::inference() {
} }
int64_t end = timeline.TimeStampUS(); int64_t end = timeline.TimeStampUS();
res->p_size = 0;
AddBlobInfo(res, start); AddBlobInfo(res, start);
AddBlobInfo(res, end); AddBlobInfo(res, end);
......
include_directories(SYSTEM ${CMAKE_CURRENT_LIST_DIR}/include) include_directories(SYSTEM ${CMAKE_CURRENT_LIST_DIR}/include)
set(SRC_LIST ${CMAKE_CURRENT_LIST_DIR}/src/test_rocksdb.cpp set(SRC_LIST ${CMAKE_CURRENT_LIST_DIR}/src/rockskvdb_impl.cpp
${CMAKE_CURRENT_LIST_DIR}/src/rockskvdb_impl.cpp
${CMAKE_CURRENT_LIST_DIR}/src/param_dict_mgr_impl.cpp ${CMAKE_CURRENT_LIST_DIR}/src/param_dict_mgr_impl.cpp
${CMAKE_CURRENT_LIST_DIR}/src/mock_param_dict_impl.cpp ${CMAKE_CURRENT_LIST_DIR}/src/mock_param_dict_impl.cpp
${CMAKE_CURRENT_LIST_DIR}/src/paddle_rocksdb.cpp ${CMAKE_CURRENT_LIST_DIR}/src/paddle_rocksdb.cpp)
${CMAKE_CURRENT_LIST_DIR}/src/gtest_kvdb.cpp)
add_library(kvdb ${SRC_LIST}) add_library(kvdb ${SRC_LIST})
add_dependencies(kvdb rocksdb) add_dependencies(kvdb rocksdb)
install(TARGETS kvdb ARCHIVE DESTINATION ${PADDLE_SERVING_INSTALL_DIR}/lib/) install(TARGETS kvdb ARCHIVE DESTINATION ${PADDLE_SERVING_INSTALL_DIR}/lib/)
add_executable(kvdb_test ${SRC_LIST})
add_dependencies(kvdb_test rocksdb)
target_link_libraries(kvdb_test rocksdb bz2 snappy zlib gtest)
#target_include_directories(kvdb_test PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include/kvdb)
set(SRC_LIST2 ${CMAKE_CURRENT_LIST_DIR}/src/gtest_db_thread.cpp set(SRC_LIST2 ${CMAKE_CURRENT_LIST_DIR}/src/rockskvdb_impl.cpp
${CMAKE_CURRENT_LIST_DIR}/src/rockskvdb_impl.cpp
${CMAKE_CURRENT_LIST_DIR}/src/param_dict_mgr_impl.cpp ${CMAKE_CURRENT_LIST_DIR}/src/param_dict_mgr_impl.cpp
${CMAKE_CURRENT_LIST_DIR}/src/mock_param_dict_impl.cpp ${CMAKE_CURRENT_LIST_DIR}/src/mock_param_dict_impl.cpp
${CMAKE_CURRENT_LIST_DIR}/src/paddle_rocksdb.cpp) ${CMAKE_CURRENT_LIST_DIR}/src/paddle_rocksdb.cpp)
add_executable(db_thread ${SRC_LIST2})
add_dependencies(db_thread rocksdb)
target_link_libraries(db_thread rocksdb bz2 snappy zlib gtest)
#target_include_directories(db_thread PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include/kvdb)
set(SRC_LIST3 ${CMAKE_CURRENT_LIST_DIR}/src/gtest_db_func.cpp
${CMAKE_CURRENT_LIST_DIR}/src/rockskvdb_impl.cpp
${CMAKE_CURRENT_LIST_DIR}/src/param_dict_mgr_impl.cpp
${CMAKE_CURRENT_LIST_DIR}/src/mock_param_dict_impl.cpp
${CMAKE_CURRENT_LIST_DIR}/src/paddle_rocksdb.cpp)
add_executable(db_func ${SRC_LIST3})
add_dependencies(db_func rocksdb)
target_link_libraries(db_func rocksdb bz2 snappy zlib gtest)
#target_include_directories(db_func PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include/kvdb)
install(TARGETS kvdb_test
RUNTIME DESTINATION ${PADDLE_SERVING_INSTALL_DIR}/demo/kvdb_test)
install(TARGETS db_thread
RUNTIME DESTINATION ${PADDLE_SERVING_INSTALL_DIR}/demo/db_thread)
install(TARGETS db_func
RUNTIME DESTINATION ${PADDLE_SERVING_INSTALL_DIR}/demo/db_func)
file(GLOB kvdb_headers "${CMAKE_CURRENT_LIST_DIR}/include/kvdb/*.h") file(GLOB kvdb_headers "${CMAKE_CURRENT_LIST_DIR}/include/kvdb/*.h")
install(FILES ${kvdb_headers} DESTINATION install(FILES ${kvdb_headers} DESTINATION
${PADDLE_SERVING_INSTALL_DIR}/include/kvdb/) ${PADDLE_SERVING_INSTALL_DIR}/include/kvdb/)
# 如何编译PaddleServing
### 获取代码
``` python
git clone https://github.com/PaddlePaddle/Serving
git submodule update --init --recursive
```
### 编译Server部分
#### 集成CPU版本Paddle Inference Library
``` shell
cmake -DPYTHON_INCLUDE_DIR=$PYTHONROOT/include/python2.7/ -DPYTHON_LIBRARIES=$PYTHONROOT/lib/libpython2.7.so -DPYTHON_EXECUTABLE=/home/users/dongdaxiang/software/baidu/third-party/python/bin/python -DCLIENT_ONLY=OFF ..
make -j10
```
#### 集成GPU版本Paddle Inference Library
``` shell
cmake -DPYTHON_INCLUDE_DIR=$PYTHONROOT/include/python2.7/ -DPYTHON_LIBRARIES=$PYTHONROOT/lib/libpython2.7.so -DPYTHON_EXECUTABLE=/home/users/dongdaxiang/software/baidu/third-party/python/bin/python -DCLIENT_ONLY=ON -DWITH_GPU=ON ..
make -j10
```
### 编译Client部分
``` shell
cmake -DPYTHON_INCLUDE_DIR=$PYTHONROOT/include/python2.7/ -DPYTHON_LIBRARIES=$PYTHONROOT/lib/libpython2.7.so -DPYTHON_EXECUTABLE=/home/users/dongdaxiang/software/baidu/third-party/python/bin/python -DCLIENT_ONLY=ON ..
make -j10
```
...@@ -28,7 +28,7 @@ func main() { ...@@ -28,7 +28,7 @@ func main() {
var config_file_path string var config_file_path string
config_file_path = os.Args[1] config_file_path = os.Args[1]
handle := serving_client.LoadModelConfig(config_file_path) handle := serving_client.LoadModelConfig(config_file_path)
handle = serving_client.Connect("127.0.0.1", "9292", handle) handle = serving_client.Connect("127.0.0.1", "9393", handle)
test_file_path := os.Args[2] test_file_path := os.Args[2]
fi, err := os.Open(test_file_path) fi, err := os.Open(test_file_path)
......
...@@ -43,11 +43,12 @@ type FetchInst struct { ...@@ -43,11 +43,12 @@ type FetchInst struct {
type Request struct { type Request struct {
Insts []FeedInst `json:"insts"` Insts []FeedInst `json:"insts"`
FetchVarNames []string `json:"fetch_var_names"` FetchVarNames []string `json:"fetch_var_names"`
ProfileServer bool `json:"profile_server"`
} }
type Response struct { type Response struct {
Insts []FetchInst `json:"insts"` Insts []FetchInst `json:"insts"`
MeanInferUs float32 `json:"mean_infer_us"` ProfileTime []int64 `json:"profile_time"`
} }
type Handle struct { type Handle struct {
...@@ -125,9 +126,13 @@ func Predict(handle Handle, int_feed_map map[string][]int64, fetch []string) map ...@@ -125,9 +126,13 @@ func Predict(handle Handle, int_feed_map map[string][]int64, fetch []string) map
inst.TensorArray = tensor_array inst.TensorArray = tensor_array
var profile_server bool
profile_server = false
req := &Request{ req := &Request{
Insts: []FeedInst{inst}, Insts: []FeedInst{inst},
FetchVarNames: fetch} FetchVarNames: fetch,
ProfileServer: profile_server}
b, err := json.Marshal(req) b, err := json.Marshal(req)
......
...@@ -259,6 +259,8 @@ class Server(object): ...@@ -259,6 +259,8 @@ class Server(object):
# currently we do not load cube # currently we do not load cube
if not self.use_local_bin: if not self.use_local_bin:
self.download_bin() self.download_bin()
else:
print("Use local bin")
command = "{} " \ command = "{} " \
"-enable_model_toolkit " \ "-enable_model_toolkit " \
"-inferservice_path {} " \ "-inferservice_path {} " \
...@@ -283,5 +285,7 @@ class Server(object): ...@@ -283,5 +285,7 @@ class Server(object):
self.resource_fn, self.resource_fn,
self.workdir, self.workdir,
self.workflow_fn, self.workflow_fn,
self.num_threads,) self.num_threads)
print("Going to Run Comand")
print(command)
os.system(command) os.system(command)
# 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.serve --model ./serving_server_model --port 9292
"""
import argparse
def parse_args():
parser = argparse.ArgumentParser("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")
return parser.parse_args()
def start_standard_model():
args = parse_args()
thread_num = args.thread
model = args.model
port = args.port
workdir = args.workdir
device = args.device
if model == "":
print("You must specify your serving model")
exit(-1)
import paddle_serving_server as serving
op_maker = serving.OpMaker()
read_op = op_maker.create('general_reader')
general_infer_op = op_maker.create('general_infer')
general_response_op = op_maker.create('general_response')
op_seq_maker = serving.OpSeqMaker()
op_seq_maker.add_op(read_op)
op_seq_maker.add_op(general_infer_op)
op_seq_maker.add_op(general_response_op)
server = serving.Server()
server.set_op_sequence(op_seq_maker.get_op_sequence())
server.set_num_threads(thread_num)
server.load_model_config(model)
server.prepare_server(workdir=workdir, port=port, device=device)
server.run_server()
if __name__ == "__main__":
start_standard_model()
...@@ -272,4 +272,6 @@ class Server(object): ...@@ -272,4 +272,6 @@ class Server(object):
self.workflow_fn, self.workflow_fn,
self.num_threads, self.num_threads,
self.gpuid,) self.gpuid,)
print("Going to Run Comand")
print(command)
os.system(command) os.system(command)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册