diff --git a/paddle/fluid/lite/api/cxx_api.h b/paddle/fluid/lite/api/cxx_api.h index f7016d5688a021573cb20cc5d6ffc1b38ebae6a2..a5c34fad37ac9a6662796f08b16aa38e710c1299 100644 --- a/paddle/fluid/lite/api/cxx_api.h +++ b/paddle/fluid/lite/api/cxx_api.h @@ -15,6 +15,8 @@ #pragma once #include "paddle/fluid/lite/core/op_executor.h" #include "paddle/fluid/lite/core/op_lite.h" +#include "paddle/fluid/lite/core/optimizer.h" +#include "paddle/fluid/lite/core/program.h" #include "paddle/fluid/lite/model_parser/model_parser.h" namespace paddle { @@ -28,34 +30,23 @@ class Predictor { void Build(const std::string& model_path, const std::vector& valid_places) { - CHECK(!executor_.get()) << "duplicate build found"; CHECK(!scope_.get()) << "duplicate build found"; framework::proto::ProgramDesc prog; LoadModel(model_path, scope_.get(), &prog); framework::ProgramDesc prog_desc(prog); - executor_.reset(new Executor(prog_desc, scope_.get(), valid_places)); - } - - // Get a tensor for input from scope directly. - Tensor* GetInputTensor(const std::string& name) { - auto* var = executor_->exec_scope()->FindVar(name); - CHECK(var) << "no tensor called " << name << " exists"; - return var->GetMutable(); - } + Program program(prog_desc, scope_, valid_places); - // Get a tensor for output from scope directly. - const Tensor* GetOutputTensor(const std::string& name) { - auto* var = executor_->exec_scope()->FindVar(name); - CHECK(var) << "no tensor called " << name << " exists"; - return &var->Get(); + Optimizer optimizer; + optimizer.Run(std::move(program), valid_places); + program_ = optimizer.GenRuntimeProgram(); } - void Run() { executor_->Run(); } + void Run() { program_->Run(); } private: std::shared_ptr scope_; - std::unique_ptr executor_; + std::unique_ptr program_; }; } // namespace lite diff --git a/paddle/fluid/lite/core/kernel.h b/paddle/fluid/lite/core/kernel.h index fef32ba3bc241df62b3147dd22ada92d4ca2d49b..6bba59263ace64884d4737ca490855d8ae964f1a 100644 --- a/paddle/fluid/lite/core/kernel.h +++ b/paddle/fluid/lite/core/kernel.h @@ -177,7 +177,6 @@ class ParamTypeRegistry { const ParamType* Retrieve(const Place& place, const std::string& op_type, const std::string& arg_name) { KernelIdTy key{op_type, place, io, arg_name}; - LOG(INFO) << "Looking for " << key; auto it = types_.find(key); if (it == types_.end()) return nullptr; return &it->second; diff --git a/paddle/fluid/lite/core/mir/CMakeLists.txt b/paddle/fluid/lite/core/mir/CMakeLists.txt index 85fdfa24c1952e9aca15e2b2b53558f4adb7ebae..f003470ffcfb4fcc560808f7d96004e916e26c90 100644 --- a/paddle/fluid/lite/core/mir/CMakeLists.txt +++ b/paddle/fluid/lite/core/mir/CMakeLists.txt @@ -5,10 +5,10 @@ cc_library(mir_pass_manager SRCS pass_manager.cc DEPS mir_pass mir_ssa_graph) cc_library(mir_pass_registry SRCS pass_registry.cc DEPS mir_pass_manager) cc_library(mir_passes SRCS static_kernel_pick_pass.cc + variable_place_inference_pass.cc io_complement_pass.cc graph_visualize_pass.cc generate_program_pass.cc - variable_place_inference_pass.cc demo_pass.cc DEPS mir_pass types_lite) diff --git a/paddle/fluid/lite/core/mir/generate_program_pass.cc b/paddle/fluid/lite/core/mir/generate_program_pass.cc index 484edb113272400917442ef12798abd96faa97a7..0e47d6b02ca963f00e54d113c077fb88efb33c19 100644 --- a/paddle/fluid/lite/core/mir/generate_program_pass.cc +++ b/paddle/fluid/lite/core/mir/generate_program_pass.cc @@ -23,7 +23,8 @@ void GenerateProgramPass::Apply(std::unique_ptr& graph) { for (auto& item : graph->InstructTopologicalOrder()) { if (item->IsInstruct()) { auto& instruct = item->AsInstruct(); - kernels_.emplace_back(std::move(instruct.valid_kernels.front())); + insts_.emplace_back(instruct.op, + std::move(instruct.valid_kernels.front())); } } } diff --git a/paddle/fluid/lite/core/mir/generate_program_pass.h b/paddle/fluid/lite/core/mir/generate_program_pass.h index 0421f5f2adafdabbab3868771b3c4502765e6ad9..0a16afb1bed4bafb1627d3694a75357a00db2a1c 100644 --- a/paddle/fluid/lite/core/mir/generate_program_pass.h +++ b/paddle/fluid/lite/core/mir/generate_program_pass.h @@ -30,10 +30,14 @@ class GenerateProgramPass : public ProgramPass { public: void Apply(std::unique_ptr& graph) override; - std::list>& kernels() { return kernels_; } + std::unique_ptr GenProgram() { + std::unique_ptr program( + new RuntimeProgram(std::move(insts_))); + return program; + } private: - std::list> kernels_; + std::vector insts_; }; } // namespace mir diff --git a/paddle/fluid/lite/core/mir/io_complement_pass.cc b/paddle/fluid/lite/core/mir/io_complement_pass.cc index c1b3a2c248a207403cdf8ff0dc4a54130f1fd606..e962c8dae4eb94c87a57ff51182b13f7bd09799b 100644 --- a/paddle/fluid/lite/core/mir/io_complement_pass.cc +++ b/paddle/fluid/lite/core/mir/io_complement_pass.cc @@ -19,8 +19,28 @@ namespace paddle { namespace lite { namespace mir { -void IoComplementPass::Apply(std::unique_ptr &graph) { - // Start from inputs of the graph, those should should have place set. +void IoComplementPass::Apply(std::unique_ptr& graph) { + // Start from inputs of the graph, those should have place set. + for (auto& node : graph->mutable_nodes()) { + if (!node.IsInstruct()) continue; + auto& inst = node.AsInstruct(); + + // inputs + for (auto* in : node.inlinks) { + CHECK(in->IsArgument()); + auto name = in->AsArgument().name; + std::string tmp; + CHECK(inst.op_info->GetInputArgname(name, &tmp)); + auto type = + ParamTypeRegistry::Global().Retrieve( + inst.place, inst.op_type, tmp); + CHECK(type) << "no param type found for " << inst.op_type << ":" << name + << " " << inst.place; + if (type->tensor_place != inst.place) { + LOG(INFO) << "found IO unmatched tensor"; + } + } + } } } // namespace mir diff --git a/paddle/fluid/lite/core/mir/node.h b/paddle/fluid/lite/core/mir/node.h index b5af9d3d04ce25ecd36490ed5e70ca895da0d6f5..2077bddc839e54e0f063c9c401378f8a25312fbc 100644 --- a/paddle/fluid/lite/core/mir/node.h +++ b/paddle/fluid/lite/core/mir/node.h @@ -48,6 +48,11 @@ class Node { std::shared_ptr op_info; // TODO(Superjomn) make this a shared_ptr for resource safety. std::shared_ptr op; // we hold op to run InferShape + + KernelBase& picked_kernel() { + CHECK(!valid_kernels.empty()); + return *valid_kernels.front(); + } }; struct Argument { diff --git a/paddle/fluid/lite/core/op_executor.cc b/paddle/fluid/lite/core/op_executor.cc index ce71e4de2b8f6ee4332a47e7d26876f75e0d75fd..43468c2358eb5cee65230af53f6469d7c25d6800 100644 --- a/paddle/fluid/lite/core/op_executor.cc +++ b/paddle/fluid/lite/core/op_executor.cc @@ -11,3 +11,9 @@ // 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 "paddle/fluid/lite/core/op_executor.h" + +namespace paddle { +namespace lite {} // namespace lite +} // namespace paddle diff --git a/paddle/fluid/lite/core/op_executor.h b/paddle/fluid/lite/core/op_executor.h index 126467a9a2a2d98440082350fa1d4bb74b72c8f5..d5e63a5c8d0f2bdf466be16ba8964a048438e08f 100644 --- a/paddle/fluid/lite/core/op_executor.h +++ b/paddle/fluid/lite/core/op_executor.h @@ -17,6 +17,7 @@ #include "paddle/fluid/lite/core/op_lite.h" #include "paddle/fluid/lite/core/op_registry.h" #include "paddle/fluid/lite/core/program.h" +#include "paddle/fluid/lite/core/program.h" #include "paddle/fluid/lite/core/scope.h" namespace paddle { @@ -50,5 +51,18 @@ class Executor { std::unique_ptr program_; }; +class RuntimeExecutor { + public: + RuntimeExecutor(RuntimeProgram* program) : program_(program) {} + + void Run() { + CHECK(program_); + program_->Run(); + } + + private: + RuntimeProgram* program_{}; +}; + } // namespace lite } // namespace paddle diff --git a/paddle/fluid/lite/core/op_lite.cc b/paddle/fluid/lite/core/op_lite.cc index 72b50c5a8c1b566d45ebcb92a8e08cb949cfdb6b..e1bbcfc1a6e341d331463c5e88248475937a5f94 100644 --- a/paddle/fluid/lite/core/op_lite.cc +++ b/paddle/fluid/lite/core/op_lite.cc @@ -61,5 +61,25 @@ bool OpLite::Attach(const framework::OpDesc &opdesc, lite::Scope *scope) { return AttachImpl(opdesc, scope); } +bool OpInfo::GetInputArgname(const std::string &value_name, std::string *out) { + for (auto &item : input_argument_) { + auto it = std::find(item.second.begin(), item.second.end(), value_name); + if (it != item.second.end()) { + *out = item.first; + return true; + } + } + return false; +} +bool OpInfo::GetOutputArgname(const std::string &value_name, std::string *out) { + for (auto &item : output_argument_) { + auto it = std::find(item.second.begin(), item.second.end(), value_name); + if (it != item.second.end()) { + *out = item.first; + return true; + } + } + return false; +} } // namespace lite } // namespace paddle diff --git a/paddle/fluid/lite/core/op_lite.h b/paddle/fluid/lite/core/op_lite.h index ffb8b7b3ce0a76725e5bd397162e48555716a8c9..3fd020b176a397e8a2bf02cdece68452ca1ce08f 100644 --- a/paddle/fluid/lite/core/op_lite.h +++ b/paddle/fluid/lite/core/op_lite.h @@ -151,6 +151,8 @@ class OpInfo { const std::map> &output_argument() { return output_argument_; } + bool GetInputArgname(const std::string &value_name, std::string *out); + bool GetOutputArgname(const std::string &value_name, std::string *out); const std::list &input_argnames() const { return input_argnames_; diff --git a/paddle/fluid/lite/core/optimizer.h b/paddle/fluid/lite/core/optimizer.h index 38c53442d2745d3feeb2de57d69292f4ee61236e..d6e170b775be937940b39a3e21ae00bf8e4038a2 100644 --- a/paddle/fluid/lite/core/optimizer.h +++ b/paddle/fluid/lite/core/optimizer.h @@ -15,8 +15,10 @@ #pragma once #include #include +#include "paddle/fluid/lite/core/mir/generate_program_pass.h" #include "paddle/fluid/lite/core/mir/pass_manager.h" #include "paddle/fluid/lite/core/mir/ssa_graph.h" +#include "paddle/fluid/lite/core/program.h" namespace paddle { namespace lite { @@ -36,9 +38,11 @@ class Optimizer { } // Generate a new program based on the mir graph. - std::unique_ptr GenProgram() { + std::unique_ptr GenRuntimeProgram() { std::unique_ptr res; - return res; + auto pass = mir::PassManager::Global().LookUp( + "generate_program_pass"); + return pass->GenProgram(); } // Generate C++ code which combines the inference program, model and weights. diff --git a/paddle/fluid/lite/core/optimizer_test.cc b/paddle/fluid/lite/core/optimizer_test.cc index f363bf3e83598cb6ade8f3c1a9f614efba5d92f9..b1acd697534f71d5af9160afdad96edf101afa91 100644 --- a/paddle/fluid/lite/core/optimizer_test.cc +++ b/paddle/fluid/lite/core/optimizer_test.cc @@ -37,12 +37,8 @@ TEST(Optimizer, test) { .ConsiderPrecision(); optimizer.Run(std::move(program), places); - - auto* program_pass = - mir::PassManager::Global().LookUp( - "generate_program_pass"); - auto& kernels = program_pass->kernels(); - LOG(INFO) << "get kernels: " << kernels.size(); + auto runtime_program = optimizer.GenRuntimeProgram(); + LOG(INFO) << "num instructions " << runtime_program->num_instructions(); } } // namespace lite diff --git a/paddle/fluid/lite/core/program.h b/paddle/fluid/lite/core/program.h index 14eb0eda382d4f8928ac2f5b209790782d721053..e19ecc0f569759ad3e5dbe8439f2b6087d5f4a45 100644 --- a/paddle/fluid/lite/core/program.h +++ b/paddle/fluid/lite/core/program.h @@ -18,6 +18,7 @@ #include #include "paddle/fluid/framework/program_desc.h" #include "paddle/fluid/lite/core/kernel.h" +#include "paddle/fluid/lite/core/kernel.h" #include "paddle/fluid/lite/core/op_lite.h" #include "paddle/fluid/lite/core/op_registry.h" @@ -86,5 +87,43 @@ struct Program { } }; +struct Instruction { + Instruction(const std::shared_ptr& op, + std::unique_ptr&& kernel) + : op_(op), kernel_(std::move(kernel)) {} + + void Run() { + CHECK(op_); + CHECK(kernel_); + op_->InferShape(); + kernel_->Run(); + } + + private: + std::shared_ptr op_; + std::unique_ptr kernel_; +}; + +/* + * A program contains kernels for runtime. + */ +class RuntimeProgram { + public: + explicit RuntimeProgram(std::vector&& instruction) + : instructions_(std::move(instruction)) {} + + void Run() { + for (auto& inst : instructions_) { + inst.Run(); + } + } + + size_t num_instructions() const { return instructions_.size(); } + + private: + RuntimeProgram(const RuntimeProgram&) = delete; + std::vector instructions_; +}; + } // namespace lite } // namespace paddle diff --git a/paddle/fluid/lite/core/target_wrapper.h b/paddle/fluid/lite/core/target_wrapper.h index 7713938774af150d1c954f0bf1e91d50620829b7..a60986c2636a6ff5a91f09e98aa9a720cc8c22c9 100644 --- a/paddle/fluid/lite/core/target_wrapper.h +++ b/paddle/fluid/lite/core/target_wrapper.h @@ -84,6 +84,8 @@ struct Place { layout == other.layout && device == other.device; } + bool operator!=(const Place& other) const { return !(*this == other); } + friend bool operator<(const Place& a, const Place& b) { if (a.target != b.target) return a.target < b.target; if (a.precision != b.precision) return a.precision < b.precision; @@ -92,6 +94,11 @@ struct Place { return true; } + friend std::ostream& operator<<(std::ostream& os, const Place& other) { + os << other.DebugString(); + return os; + } + std::string DebugString() const { std::stringstream os; os << TargetToStr(target) << "/" << PrecisionToStr(precision) << "/"