提交 b9ab5a9b 编写于 作者: G guru4elephant

add infer time interface, add auc and acc metric

上级 e7b11be2
...@@ -26,4 +26,5 @@ endif() ...@@ -26,4 +26,5 @@ endif()
if (NOT CLIENT_ONLY) if (NOT CLIENT_ONLY)
add_subdirectory(predictor) add_subdirectory(predictor)
add_subdirectory(general-server) add_subdirectory(general-server)
add_subdirectory(util)
endif() endif()
...@@ -51,6 +51,7 @@ class PredictorClient { ...@@ -51,6 +51,7 @@ class PredictorClient {
const std::string& conf_file); const std::string& conf_file);
int create_predictor(); int create_predictor();
int destroy_predictor();
std::vector<std::vector<float>> predict( std::vector<std::vector<float>> predict(
const std::vector<std::vector<float>>& float_feed, const std::vector<std::vector<float>>& float_feed,
......
...@@ -83,6 +83,11 @@ void PredictorClient::set_predictor_conf(const std::string &conf_path, ...@@ -83,6 +83,11 @@ void PredictorClient::set_predictor_conf(const std::string &conf_path,
_predictor_conf = conf_file; _predictor_conf = conf_file;
} }
int PredictorClient::destroy_predictor() {
_api.thrd_finalize();
_api.destroy();
}
int PredictorClient::create_predictor() { int PredictorClient::create_predictor() {
if (_api.create(_predictor_path.c_str(), _predictor_conf.c_str()) != 0) { if (_api.create(_predictor_path.c_str(), _predictor_conf.c_str()) != 0) {
LOG(ERROR) << "Predictor Creation Failed"; LOG(ERROR) << "Predictor Creation Failed";
...@@ -101,7 +106,9 @@ std::vector<std::vector<float>> PredictorClient::predict( ...@@ -101,7 +106,9 @@ std::vector<std::vector<float>> PredictorClient::predict(
if (fetch_name.size() == 0) { if (fetch_name.size() == 0) {
return fetch_result; return fetch_result;
} }
fetch_result.resize(fetch_name.size());
// we save infer_us at fetch_result[fetch_name.size()]
fetch_result.resize(fetch_name.size() + 1);
_api.thrd_clear(); _api.thrd_clear();
_predictor = _api.fetch_predictor("general_model"); _predictor = _api.fetch_predictor("general_model");
...@@ -179,6 +186,8 @@ std::vector<std::vector<float>> PredictorClient::predict( ...@@ -179,6 +186,8 @@ std::vector<std::vector<float>> PredictorClient::predict(
*(const float *)res.insts(0).tensor_array(idx).data(i).c_str(); *(const float *)res.insts(0).tensor_array(idx).data(i).c_str();
} }
} }
fetch_result[fetch_name.size()].resize(1);
fetch_result[fetch_name.size()][0] = res.mean_infer_us();
} }
return fetch_result; return fetch_result;
......
...@@ -43,6 +43,8 @@ PYBIND11_MODULE(serving_client, m) { ...@@ -43,6 +43,8 @@ PYBIND11_MODULE(serving_client, m) {
}) })
.def("create_predictor", .def("create_predictor",
[](PredictorClient &self) { self.create_predictor(); }) [](PredictorClient &self) { self.create_predictor(); })
.def("destroy_predictor",
[](PredictorClient &self) { self.destroy_predictor(); })
.def("predict", .def("predict",
[](PredictorClient &self, [](PredictorClient &self,
const std::vector<std::vector<float>> &float_feed, const std::vector<std::vector<float>> &float_feed,
......
...@@ -3,7 +3,7 @@ include(op/CMakeLists.txt) ...@@ -3,7 +3,7 @@ include(op/CMakeLists.txt)
include(proto/CMakeLists.txt) include(proto/CMakeLists.txt)
add_executable(serving ${serving_srcs}) add_executable(serving ${serving_srcs})
add_dependencies(serving pdcodegen fluid_cpu_engine pdserving paddle_fluid add_dependencies(serving pdcodegen fluid_cpu_engine pdserving paddle_fluid
opencv_imgcodecs cube-api) opencv_imgcodecs cube-api utils)
if (WITH_GPU) if (WITH_GPU)
add_dependencies(serving fluid_gpu_engine) add_dependencies(serving fluid_gpu_engine)
endif() endif()
...@@ -23,6 +23,7 @@ target_link_libraries(serving paddle_fluid ${paddle_depend_libs}) ...@@ -23,6 +23,7 @@ target_link_libraries(serving paddle_fluid ${paddle_depend_libs})
target_link_libraries(serving pdserving) target_link_libraries(serving pdserving)
target_link_libraries(serving cube-api) target_link_libraries(serving cube-api)
target_link_libraries(serving utils)
target_link_libraries(serving kvdb rocksdb) target_link_libraries(serving kvdb rocksdb)
......
...@@ -21,12 +21,13 @@ ...@@ -21,12 +21,13 @@
#include "core/predictor/framework/infer.h" #include "core/predictor/framework/infer.h"
#include "core/predictor/framework/memory.h" #include "core/predictor/framework/memory.h"
#include "core/predictor/framework/resource.h" #include "core/predictor/framework/resource.h"
#include "core/util/include/timer.h"
namespace baidu { namespace baidu {
namespace paddle_serving { namespace paddle_serving {
namespace serving { namespace serving {
using baidu::paddle_serving::Timer;
using baidu::paddle_serving::predictor::MempoolWrapper; using baidu::paddle_serving::predictor::MempoolWrapper;
using baidu::paddle_serving::predictor::general_model::Tensor; using baidu::paddle_serving::predictor::general_model::Tensor;
using baidu::paddle_serving::predictor::general_model::Response; using baidu::paddle_serving::predictor::general_model::Response;
...@@ -54,10 +55,15 @@ int GeneralInferOp::inference() { ...@@ -54,10 +55,15 @@ int GeneralInferOp::inference() {
TensorVector *out = butil::get_object<TensorVector>(); TensorVector *out = butil::get_object<TensorVector>();
int batch_size = (*in)[0].shape[0]; int batch_size = (*in)[0].shape[0];
// infer // infer
Timer timeline;
double infer_time = 0.0;
timeline.Start();
if (InferManager::instance().infer(GENERAL_MODEL_NAME, in, out, batch_size)) { if (InferManager::instance().infer(GENERAL_MODEL_NAME, in, out, batch_size)) {
LOG(ERROR) << "Failed do infer in fluid model: " << GENERAL_MODEL_NAME; LOG(ERROR) << "Failed do infer in fluid model: " << GENERAL_MODEL_NAME;
return -1; return -1;
} }
timeline.Pause();
infer_time = timeline.ElapsedUS();
const Request *req = dynamic_cast<const Request *>(get_request_message()); const Request *req = dynamic_cast<const Request *>(get_request_message());
...@@ -79,6 +85,8 @@ int GeneralInferOp::inference() { ...@@ -79,6 +85,8 @@ int GeneralInferOp::inference() {
// response inst with only fetch_var_names // response inst with only fetch_var_names
Response *res = mutable_data<Response>(); Response *res = mutable_data<Response>();
res->set_mean_infer_us(infer_time);
for (int i = 0; i < batch_size; ++i) { for (int i = 0; i < batch_size; ++i) {
FetchInst *fetch_inst = res->add_insts(); FetchInst *fetch_inst = res->add_insts();
for (auto & idx : fetch_index) { for (auto & idx : fetch_index) {
......
...@@ -103,12 +103,14 @@ int GeneralReaderOp::inference() { ...@@ -103,12 +103,14 @@ int GeneralReaderOp::inference() {
VLOG(2) << "print general model config done."; VLOG(2) << "print general model config done.";
// check // check
/*
res->reader_status = conf_check(req, model_config); res->reader_status = conf_check(req, model_config);
if (res->reader_status != 0) { if (res->reader_status != 0) {
LOG(INFO) << "model conf of server:"; LOG(INFO) << "model conf of server:";
resource.print_general_model_config(model_config); resource.print_general_model_config(model_config);
return 0; return 0;
} }
*/
// package tensor // package tensor
elem_type.resize(var_num); elem_type.resize(var_num);
...@@ -201,13 +203,14 @@ int GeneralReaderOp::inference() { ...@@ -201,13 +203,14 @@ int GeneralReaderOp::inference() {
VLOG(2) << "read data from client success"; VLOG(2) << "read data from client success";
// print request // print request
/*
std::ostringstream oss; std::ostringstream oss;
int64_t *example = reinterpret_cast<int64_t *>((*in)[0].data.data()); int64_t *example = reinterpret_cast<int64_t *>((*in)[0].data.data());
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
oss << *(example + i) << " "; oss << *(example + i) << " ";
} }
VLOG(2) << "head element of first feed var : " << oss.str(); VLOG(2) << "head element of first feed var : " << oss.str();
// */
return 0; return 0;
} }
DEFINE_OP(GeneralReaderOp); DEFINE_OP(GeneralReaderOp);
......
...@@ -40,6 +40,7 @@ message Request { ...@@ -40,6 +40,7 @@ message Request {
message Response { message Response {
repeated FetchInst insts = 1; repeated FetchInst insts = 1;
optional float mean_infer_us = 2;
}; };
service GeneralModelService { service GeneralModelService {
......
...@@ -40,6 +40,7 @@ message Request { ...@@ -40,6 +40,7 @@ message Request {
message Response { message Response {
repeated FetchInst insts = 1; repeated FetchInst insts = 1;
optional float mean_infer_us = 2;
}; };
service GeneralModelService { service GeneralModelService {
......
include(src/CMakeLists.txt)
add_library(utils ${util_srcs})
/* 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. */
#pragma once
#include <stdlib.h>
namespace baidu {
namespace paddle_serving {
// A Standard Timer implementation for debugging
class Timer {
public:
// a timer class for profiling
// Reset() will be called during initialization
// all timing variables will be set 0 in Reset()
Timer() { Reset(); }
void Reset();
void Start();
void Pause();
// Resume will get current system time
void Resume();
int Count();
// return elapsed time in us
double ElapsedUS();
// return elapsed time in ms
double ElapsedMS();
// return elapsed time in sec
double ElapsedSec();
private:
struct timeval _start;
struct timeval _now;
int _count;
int64_t _elapsed;
bool _paused;
// get us difference between start and now
int64_t Tickus();
};
} // namespace paddle_serving
} // namespace baidu
FILE(GLOB srcs ${CMAKE_CURRENT_LIST_DIR}/*.cc)
LIST(APPEND util_srcs ${srcs})
/* 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. */
#include <sys/time.h>
#include "core/util/include/timer.h"
namespace baidu {
namespace paddle_serving {
void Timer::Reset() {
_start.tv_sec = 0;
_start.tv_usec = 0;
_count = 0;
_elapsed = 0;
_paused = true;
}
void Timer::Start() {
Reset();
Resume();
}
void Timer::Pause() {
if (_paused) {
return;
}
_elapsed += Tickus();
++_count;
_paused = true;
}
void Timer::Resume() {
gettimeofday(&_start, NULL);
_paused = false;
}
int Timer::Count() { return _count; }
double Timer::ElapsedUS() { return static_cast<double>(_elapsed); }
double Timer::ElapsedMS() { return _elapsed / 1000.0; }
double Timer::ElapsedSec() { return _elapsed / 1000000.0; }
int64_t Timer::Tickus() {
gettimeofday(&_now, NULL);
return (_now.tv_sec - _start.tv_sec) * 1000 * 1000L +
(_now.tv_usec - _start.tv_usec);
}
} // namespace paddle_serving
} // namespace baidu
...@@ -118,7 +118,7 @@ class Client(object): ...@@ -118,7 +118,7 @@ class Client(object):
def get_fetch_names(self): def get_fetch_names(self):
return self.fetch_names_ return self.fetch_names_
def predict(self, feed={}, fetch=[]): def predict(self, feed={}, fetch=[], debug=False):
int_slot = [] int_slot = []
float_slot = [] float_slot = []
int_feed_names = [] int_feed_names = []
...@@ -148,6 +148,9 @@ class Client(object): ...@@ -148,6 +148,9 @@ class Client(object):
for i, name in enumerate(fetch_names): for i, name in enumerate(fetch_names):
result_map[name] = result[i] result_map[name] = result[i]
if debug:
result_map["infer_time"] = result[-1][0]
return result_map return result_map
def batch_predict(self, feed_batch=[], fetch=[]): def batch_predict(self, feed_batch=[], fetch=[]):
...@@ -191,3 +194,6 @@ class Client(object): ...@@ -191,3 +194,6 @@ class Client(object):
result_map_batch.append(result_map) result_map_batch.append(result_map)
return result_map_batch return result_map_batch
def release(self):
self.client_handle_.destroy_predictor()
...@@ -12,3 +12,4 @@ ...@@ -12,3 +12,4 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from auc import auc from auc import auc
from acc import acc
# 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.
def acc(prob, label, threshold):
# we support prob is the probability for label to be one
assert len(prob) == len(label)
total = len(prob)
right = 0
for i in range(len(prob)):
if (prob - threshold) * (label - prob) > 0:
right += 1
return float(right) / total
# 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.
def tied_rank(x): def tied_rank(x):
""" """
Computes the tied rank of elements in x. Computes the tied rank of elements in x.
......
# 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.
import sys
import subprocess
from multiprocessing import Pool
class MultiThreadRunner(object):
def __init__(self):
pass
def run(self, thread_func, thread_num, global_resource):
p = Pool(thread_num)
result_list = []
for i in range(thread_num):
result_list.append(
p.apply_async(thread_func, [i + 1, global_resource]))
p.close()
p.join()
return_result = result_list[0].get()
for i in range(1, thread_num, 1):
tmp_result = result_list[i].get()
for i, item in enumerate(tmp_result):
return_result[i].extend(tmp_result[i])
return return_result
...@@ -35,7 +35,8 @@ REQUIRED_PACKAGES = [ ...@@ -35,7 +35,8 @@ REQUIRED_PACKAGES = [
packages=['paddle_serving_client', packages=['paddle_serving_client',
'paddle_serving_client.proto', 'paddle_serving_client.proto',
'paddle_serving_client.io', 'paddle_serving_client.io',
'paddle_serving_client.metric'] 'paddle_serving_client.metric',
'paddle_serving_client.utils']
package_data={'paddle_serving_client': ['serving_client.so']} package_data={'paddle_serving_client': ['serving_client.so']}
package_dir={'paddle_serving_client': package_dir={'paddle_serving_client':
'${PADDLE_SERVING_BINARY_DIR}/python/paddle_serving_client', '${PADDLE_SERVING_BINARY_DIR}/python/paddle_serving_client',
...@@ -44,7 +45,9 @@ package_dir={'paddle_serving_client': ...@@ -44,7 +45,9 @@ package_dir={'paddle_serving_client':
'paddle_serving_client.io': 'paddle_serving_client.io':
'${PADDLE_SERVING_BINARY_DIR}/python/paddle_serving_client/io', '${PADDLE_SERVING_BINARY_DIR}/python/paddle_serving_client/io',
'paddle_serving_client.metric': 'paddle_serving_client.metric':
'${PADDLE_SERVING_BINARY_DIR}/python/paddle_serving_client/metric'} '${PADDLE_SERVING_BINARY_DIR}/python/paddle_serving_client/metric',
'paddle_serving_client.utils':
'${PADDLE_SERVING_BINARY_DIR}/python/paddle_serving_client/utils'}
setup( setup(
name='paddle-serving-client', name='paddle-serving-client',
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册