// Copyright (c) 2018 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 #include #include "paddle/fluid/framework/feed_fetch_method.h" #include "paddle/fluid/framework/lod_rank_table.h" #include "paddle/fluid/framework/lod_tensor_array.h" #include "paddle/fluid/framework/naive_executor.h" #include "paddle/fluid/framework/op_registry.h" #include "paddle/fluid/framework/reader.h" #include "paddle/fluid/string/pretty_log.h" namespace paddle { namespace framework { // These code can be shared with Executor. static void InitializeVariable(Variable *var, proto::VarType::Type var_type) { if (var_type == proto::VarType::LOD_TENSOR) { var->GetMutable(); } else if (var_type == proto::VarType::SELECTED_ROWS) { var->GetMutable(); } else if (var_type == proto::VarType::FEED_MINIBATCH) { var->GetMutable(); } else if (var_type == proto::VarType::FETCH_LIST) { var->GetMutable(); } else if (var_type == proto::VarType::STEP_SCOPES) { var->GetMutable>(); } else if (var_type == proto::VarType::LOD_RANK_TABLE) { var->GetMutable(); } else if (var_type == proto::VarType::LOD_TENSOR_ARRAY) { var->GetMutable(); } else if (var_type == proto::VarType::PLACE_LIST) { var->GetMutable(); } else if (var_type == proto::VarType::READER) { var->GetMutable(); } else if (var_type == proto::VarType::RAW) { // GetMutable will be called in operator } else { PADDLE_THROW( "Variable type %d is not in " "[LOD_TENSOR, SELECTED_ROWS, FEED_MINIBATCH, FETCH_LIST, " "LOD_RANK_TABLE, PLACE_LIST, READER, CHANNEL, RAW]", var_type); } } void NaiveExecutor::Prepare(Scope *scope, const ProgramDesc &program_desc, int block_id, bool with_feed_fetch_ops) { if (!scope) { scope_ = new framework::Scope; } else { scope_ = scope; } VLOG(3) << "NaiveExecutor init with scope " << scope; CreateOps(program_desc, block_id, with_feed_fetch_ops); } void NaiveExecutor::Run() { #ifndef PADDLE_ON_INFERENCE LOG_FIRST_N(WARNING, 15) << "The NaiveExecutor can not work properly if the " "cmake flag ON_INFER is not set."; LOG_FIRST_N(WARNING, 15) << "Unlike the training phase, all the scopes and " "variables will be reused to save the allocation " "overhead."; LOG_FIRST_N(WARNING, 15) << "Please re-compile the inference library by " "setting the cmake flag ON_INFER=ON if you are " "running Paddle Inference"; #endif // PADDLE_ON_INFERENCE for (auto &op : ops_) { VLOG(3) << std::this_thread::get_id() << " run " << op->Type() << " on scope " << scope_; op->SetIsCalledByExecutor(false); op->Run(*scope_, place_); } } void NaiveExecutor::CreateVariables(const ProgramDesc &desc, int block_id, bool persistable, Scope *scope) { PADDLE_ENFORCE_NOT_NULL(scope); auto &global_block = desc.Block(block_id); const auto *anc = scope; PADDLE_ENFORCE(anc->parent() != anc); while (anc->parent()) { anc = anc->parent(); } for (auto &var : global_block.AllVars()) { if (var->Name() == framework::kEmptyVarName) { continue; } if (persistable == var->Persistable()) { if (persistable) { if (!anc->FindVar(var->Name())) { auto *ptr = const_cast(anc)->Var(var->Name()); VLOG(3) << scope << " Create persistable variable " << var->Name() << ", which pointer is " << ptr; InitializeVariable(ptr, var->GetType()); } } else { auto *ptr = const_cast(scope)->Var(var->Name()); VLOG(3) << scope << " Create variable " << var->Name() << ", which pointer is " << ptr; InitializeVariable(ptr, var->GetType()); } } } } void NaiveExecutor::CreateOps(const ProgramDesc &desc, int block_id, bool with_feed_fetch_ops) { for (const auto &op_desc : desc.Block(block_id).AllOps()) { if (!with_feed_fetch_ops && (op_desc->Type() == "feed" || op_desc->Type() == "fetch")) { string::PrettyLogEndl(string::Style::detail(), "--- skip [%s], %s -> %s", op_desc->Input("X")[0], op_desc->Type(), op_desc->Output("Out")[0]); continue; } ops_.emplace_back(OpRegistry::CreateOp(*op_desc)); } } LoDTensor *NaiveExecutor::FindTensor(const std::string &name) { PADDLE_ENFORCE(scope_, "Need to init scope first"); auto *var = scope_->FindVar(name); PADDLE_ENFORCE(var, "No variable [%s] in the scope"); auto *tensor = const_cast(&var->Get()); return tensor; } void NaiveExecutor::CleanFeedFetchOps() { std::vector> ops; for (auto &op : ops_) { if (op->Type() != "feed" && op->Type() != "fetch") { ops.emplace_back(std::move(op)); } } ops_.swap(ops); } } // namespace framework } // namespace paddle