From b66052ddcd5cf025c57df5cf380dafdc77586fb7 Mon Sep 17 00:00:00 2001 From: DannyIsFunny <912790387@qq.com> Date: Sun, 22 Mar 2020 16:41:12 +0000 Subject: [PATCH] test=develop --- lite/api/cxx_api.cc | 3 +-- lite/api/cxx_api.h | 27 +++++++++++++++++++++++- lite/api/cxx_api_impl.cc | 44 +++++++++++++++++++++++----------------- lite/api/cxx_api_test.cc | 38 ++++++++++++++++++++++++++++++++++ lite/core/optimizer.h | 14 +++++++++++++ lite/core/scope.cc | 16 +++++++++++++-- lite/core/scope.h | 3 +++ 7 files changed, 121 insertions(+), 24 deletions(-) diff --git a/lite/api/cxx_api.cc b/lite/api/cxx_api.cc index 556a9e0af0..8081378ea1 100644 --- a/lite/api/cxx_api.cc +++ b/lite/api/cxx_api.cc @@ -228,7 +228,6 @@ std::vector Predictor::GetOutputs() const { const cpp::ProgramDesc &Predictor::program_desc() const { return program_desc_; } - const RuntimeProgram &Predictor::runtime_program() const { return *program_; } void Predictor::Build(const lite_api::CxxConfig &config, @@ -294,7 +293,6 @@ void Predictor::Build(const cpp::ProgramDesc &desc, inner_places.emplace_back(TARGET(kHost), PRECISION(kAny), DATALAYOUT(kAny)); inner_places.emplace_back( TARGET(kHost), PRECISION(kFloat), DATALAYOUT(kNCHW)); - const std::vector quant_dequant_op = { "fake_quantize_abs_max", "fake_quantize_range_abs_max", @@ -321,6 +319,7 @@ void Predictor::Build(const cpp::ProgramDesc &desc, } Program program(desc, scope_, inner_places); + valid_places_ = inner_places; core::KernelPickFactor factor; factor.ConsiderTarget(); diff --git a/lite/api/cxx_api.h b/lite/api/cxx_api.h index e63893cb91..79741a6318 100644 --- a/lite/api/cxx_api.h +++ b/lite/api/cxx_api.h @@ -46,6 +46,17 @@ class LITE_API Predictor { // Create a predictor with the weight variable scope set. explicit Predictor(const std::shared_ptr& root_scope) : scope_(root_scope) {} + Predictor(const cpp::ProgramDesc& desc, + const std::shared_ptr& root, + const std::vector& valid_places) + : program_desc_(desc), scope_(root) { + optimizer_ = + Optimizer(new Program(desc, scope_, valid_places), valid_places); + exec_scope_ = optimizer_.exec_scope(); + GenRuntimeProgram(); + valid_places_ = valid_places; + PrepareFeedFetch(); + } // Build from a model, with places set for hardware config. void Build( @@ -67,6 +78,16 @@ class LITE_API Predictor { const std::vector& valid_places, const std::vector& passes = {}); + std::shared_ptr Clone() const { + // CHECK(program_desc_) << "Both program and scope of current predicotr + // should be not be nullptr in Clone mode." ; + // CHECK(scope_) << "Both program and scope of current predicotr should + // be not be nullptr in Clone mode."; + auto predictor = + std::make_shared(program_desc_, scope_, valid_places_); + return predictor; + } + void GenRuntimeProgram(); // Run the predictor for a single batch of data. @@ -119,11 +140,14 @@ class LITE_API Predictor { bool program_generated_{false}; std::vector input_names_; std::vector output_names_; + std::vector valid_places_; }; class CxxPaddleApiImpl : public lite_api::PaddlePredictor { public: CxxPaddleApiImpl() {} + explicit CxxPaddleApiImpl(const std::shared_ptr& raw_predictor) + : raw_predictor_(raw_predictor) {} /// Create a new predictor from a config. void Init(const lite_api::CxxConfig& config); @@ -155,9 +179,10 @@ class CxxPaddleApiImpl : public lite_api::PaddlePredictor { bool record_info = false) override; private: - Predictor raw_predictor_; + std::shared_ptr raw_predictor_; lite_api::CxxConfig config_; std::mutex mutex_; + bool status_is_cloned_{false}; }; /* diff --git a/lite/api/cxx_api_impl.cc b/lite/api/cxx_api_impl.cc index 972210c8f9..db54e11b30 100644 --- a/lite/api/cxx_api_impl.cc +++ b/lite/api/cxx_api_impl.cc @@ -34,17 +34,21 @@ void CxxPaddleApiImpl::Init(const lite_api::CxxConfig &config) { #ifdef LITE_WITH_CUDA Env::Init(); #endif - auto places = config.valid_places(); - std::vector passes{}; - auto use_layout_preprocess_pass = - config.model_dir().find("OPENCL_PRE_PRECESS"); - VLOG(1) << "use_layout_preprocess_pass:" << use_layout_preprocess_pass; - if (places[0].target == TARGET(kOpenCL) && - use_layout_preprocess_pass != std::string::npos) { - passes = {"type_layout_cast_preprocess_pass"}; - VLOG(1) << "add pass:" << passes[0]; + if (!status_is_cloned_) { + auto places = config.valid_places(); + std::vector passes{}; + auto use_layout_preprocess_pass = + config.model_dir().find("OPENCL_PRE_PRECESS"); + VLOG(1) << "use_layout_preprocess_pass:" << use_layout_preprocess_pass; + if (places[0].target == TARGET(kOpenCL) && + use_layout_preprocess_pass != std::string::npos) { + passes = {"type_layout_cast_preprocess_pass"}; + VLOG(1) << "add pass:" << passes[0]; + } + raw_predictor_->Build(config, places, passes); + } else { + CHECK(raw_predictor_) << "The Predictor can not be nullptr in Clone mode."; } - raw_predictor_.Build(config, places, passes); mode_ = config.power_mode(); threads_ = config.threads(); @@ -61,34 +65,36 @@ void CxxPaddleApiImpl::Init(const lite_api::CxxConfig &config) { } std::unique_ptr CxxPaddleApiImpl::GetInput(int i) { - auto *x = raw_predictor_.GetInput(i); + auto *x = raw_predictor_->GetInput(i); return std::unique_ptr(new lite_api::Tensor(x)); } std::unique_ptr CxxPaddleApiImpl::GetOutput( int i) const { - const auto *x = raw_predictor_.GetOutput(i); + const auto *x = raw_predictor_->GetOutput(i); return std::unique_ptr(new lite_api::Tensor(x)); } std::vector CxxPaddleApiImpl::GetInputNames() { - return raw_predictor_.GetInputNames(); + return raw_predictor_->GetInputNames(); } std::vector CxxPaddleApiImpl::GetOutputNames() { - return raw_predictor_.GetOutputNames(); + return raw_predictor_->GetOutputNames(); } void CxxPaddleApiImpl::Run() { #ifdef LITE_WITH_ARM lite::DeviceInfo::Global().SetRunMode(mode_, threads_); #endif - raw_predictor_.Run(); + raw_predictor_->Run(); } std::shared_ptr CxxPaddleApiImpl::Clone() { std::lock_guard lock(mutex_); - auto predictor = std::make_shared(); + auto predictor = + std::make_shared(raw_predictor_->Clone()); + status_is_cloned_ = true; predictor->Init(config_); return predictor; } @@ -97,20 +103,20 @@ std::string CxxPaddleApiImpl::GetVersion() const { return version(); } std::unique_ptr CxxPaddleApiImpl::GetTensor( const std::string &name) const { - auto *x = raw_predictor_.GetTensor(name); + auto *x = raw_predictor_->GetTensor(name); return std::unique_ptr(new lite_api::Tensor(x)); } std::unique_ptr CxxPaddleApiImpl::GetInputByName( const std::string &name) { return std::unique_ptr( - new lite_api::Tensor(raw_predictor_.GetInputByName(name))); + new lite_api::Tensor(raw_predictor_->GetInputByName(name))); } void CxxPaddleApiImpl::SaveOptimizedModel(const std::string &model_dir, lite_api::LiteModelType model_type, bool record_info) { - raw_predictor_.SaveModel(model_dir, model_type, record_info); + raw_predictor_->SaveModel(model_dir, model_type, record_info); } } // namespace lite diff --git a/lite/api/cxx_api_test.cc b/lite/api/cxx_api_test.cc index cdf1e83836..768480b147 100644 --- a/lite/api/cxx_api_test.cc +++ b/lite/api/cxx_api_test.cc @@ -53,6 +53,44 @@ TEST(CXXApi, save_model) { lite_api::LiteModelType::kNaiveBuffer); } +TEST(CXXApi, clone_predictor) { + lite::Predictor predictor; + std::vector valid_places({Place{TARGET(kX86), PRECISION(kFloat)}}); + predictor.Build(FLAGS_model_dir, "", "", valid_places); + auto cloned_predictor = predictor.Clone(); + // primary predicotr + auto* input_tensor = predictor.GetInput(0); + input_tensor->Resize(std::vector({1, 100})); + auto* data = input_tensor->mutable_data(); + for (int i = 0; i < 100; i++) { + data[i] = 1; + } + + predictor.Run(); + auto* output_tensor = predictor.GetOutput(0); + auto output_shape = output_tensor->dims().Vectorize(); + ASSERT_EQ(output_shape.size(), 2); + ASSERT_EQ(output_shape[0], 1); + ASSERT_EQ(output_shape[1], 500); + + // cloned predictor + auto* cloned_input_tensor = cloned_predictor->GetInput(0); + cloned_input_tensor->Resize(std::vector({1, 100})); + auto* cloned_data = cloned_input_tensor->mutable_data(); + for (int i = 0; i < 100; i++) { + cloned_data[i] = 1; + } + cloned_predictor->Run(); + auto* cloned_output_tensor = cloned_predictor->GetOutput(0); + + int step = 50; + for (int i = 0; i < output_tensor->data_size(); i += step) { + EXPECT_NEAR(output_tensor->data()[i], + cloned_output_tensor->data()[i], + 1e-6); + } +} + /*TEST(CXXTrainer, train) { Place place({TARGET(kHost), PRECISION(kFloat), DATALAYOUT(kNCHW)}); std::vector valid_places({place}); diff --git a/lite/core/optimizer.h b/lite/core/optimizer.h index ca22c86907..cb718776b5 100644 --- a/lite/core/optimizer.h +++ b/lite/core/optimizer.h @@ -37,6 +37,20 @@ namespace lite { */ class Optimizer { public: + Optimizer() {} + + Optimizer(Program* program, const std::vector& valid_places) { + program_ = program; + valid_places_ = valid_places; + CHECK(!valid_places.empty()) << "At least one valid_place should be set"; + CHECK(!graph_) << "duplicate optimize found"; + + graph_.reset(new mir::SSAGraph); + graph_->Build(*program, valid_places); + graph_->SetValidPlaces(valid_places); + exec_scope_ = program->exec_scope(); + } + void Run(Program&& program, const std::vector& valid_places, core::KernelPickFactor kernel_pick_factor, diff --git a/lite/core/scope.cc b/lite/core/scope.cc index 775652e2a0..5fe436f875 100644 --- a/lite/core/scope.cc +++ b/lite/core/scope.cc @@ -13,11 +13,16 @@ // limitations under the License. #include "lite/core/scope.h" +#define SCOPE_KIDS_READER_LOCK lite::fluid::AutoRDLock auto_lock(&kids_lock_); +#define SCOPE_KIDS_WRITER_LOCK lite::fluid::AutoWRLock auto_lock(&kids_lock_); +#define SCOPE_VARS_READER_LOCK lite::fluid::AutoRDLock auto_lock(&vars_lock_); +#define SCOPE_VARS_WRITER_LOCK lite::fluid::AutoWRLock auto_lock(&vars_lock_); namespace paddle { namespace lite { Scope::~Scope() { + SCOPE_KIDS_WRITER_LOCK for (auto *x : kids_) { if (x) { delete x; @@ -26,12 +31,14 @@ Scope::~Scope() { } Scope &Scope::NewScope() const { + SCOPE_KIDS_WRITER_LOCK kids_.push_back(new Scope); kids_.back()->parent_ = this; return *kids_.back(); } Variable *Scope::Var(const std::string &name) { + SCOPE_VARS_WRITER_LOCK auto *var = FindVar(name); if (var) return var; @@ -45,6 +52,7 @@ Variable *Scope::FindVar(const std::string &name) const { var = FindLocalVar(name); const Scope *cur_scope = this; while (!var && cur_scope->parent()) { + // SCOPE_VARS_READER_LOCK cur_scope = cur_scope->parent(); var = cur_scope->FindLocalVar(name); } @@ -53,6 +61,7 @@ Variable *Scope::FindVar(const std::string &name) const { } Variable *Scope::FindLocalVar(const std::string &name) const { + // SCOPE_VARS_READER_LOCK auto it = vars_.find(name); if (it != vars_.end()) { return it->second.get(); @@ -62,8 +71,11 @@ Variable *Scope::FindLocalVar(const std::string &name) const { std::vector Scope::LocalVarNames() const { std::vector keys; - for (const auto &item : vars_) { - keys.push_back(item.first); + { + // SCOPE_VARS_READER_LOCK + for (const auto &item : vars_) { + keys.push_back(item.first); + } } return keys; } diff --git a/lite/core/scope.h b/lite/core/scope.h index 2593c36522..3cd7e5f161 100644 --- a/lite/core/scope.h +++ b/lite/core/scope.h @@ -20,6 +20,7 @@ #include #include #include "lite/core/variable.h" +#include "lite/fluid/rw_lock.h" namespace paddle { namespace lite { @@ -73,6 +74,8 @@ class Scope final { mutable std::list kids_; const Scope* parent_{nullptr}; std::unordered_map> vars_; + mutable lite::fluid::RWLock kids_lock_; + mutable lite::fluid::RWLock vars_lock_; }; } // namespace lite -- GitLab