diff --git a/paddle/fluid/lite/core/CMakeLists.txt b/paddle/fluid/lite/core/CMakeLists.txt index 5ad83283ee4041c410e47d59bb6dae06c50da8b1..e0cb753c0985ce513a24f81c7a4179e22554cad1 100644 --- a/paddle/fluid/lite/core/CMakeLists.txt +++ b/paddle/fluid/lite/core/CMakeLists.txt @@ -1,12 +1,15 @@ -cc_library(executor_lite SRCS executor.cc) cc_library(memory_lite SRCS memory.cc) cc_library(tensor_lite SRCS tensor.cc DEPS memory_lite) cc_library(variable_lite SRCS variable.cc) cc_library(op_registry_lite SRCS op_registry.cc) cc_library(scope_lite SRCS scope.cc) cc_library(op_lite SRCS op_lite.cc DEPS scope_lite op_registry_lite) +cc_library(executor_lite SRCS executor.cc DEPS scope_lite tensor_lite op_lite op_registry_lite + #TODO(Superjomn) remove these dependencies from original framework + proto_desc) cc_test(test_scope_lite SRCS scope_test.cc DEPS scope_lite) cc_test(test_kernel_lite SRCS kernel_test.cc DEPS target_wrapper_x86) cc_test(test_op_lite SRCS op_lite_test.cc DEPS op_lite) cc_test(test_tensor_lite SRCS tensor_test.cc) +cc_test(test_executor_lite SRCS executor_test.cc DEPS executor_lite ops_lite host_kernels) diff --git a/paddle/fluid/lite/core/executor.h b/paddle/fluid/lite/core/executor.h index ce71e4de2b8f6ee4332a47e7d26876f75e0d75fd..d73dff5908ae19fae23f1111ca52fde9c7897bc7 100644 --- a/paddle/fluid/lite/core/executor.h +++ b/paddle/fluid/lite/core/executor.h @@ -11,3 +11,67 @@ // 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 "paddle/fluid/framework/program_desc.h" +#include "paddle/fluid/lite/core/op_lite.h" +#include "paddle/fluid/lite/core/op_registry.h" +#include "paddle/fluid/lite/core/scope.h" + +namespace paddle { +namespace lite { + +// The Executor is used to run the operators. +class Executor { + public: + Executor(lite::Scope* scope, const std::vector& valid_places) + : scope_(scope), valid_places_(valid_places) {} + + // Create temporary variables. + void PrepareWorkspace(framework::ProgramDesc& program, lite::Scope* scope) { + CHECK(!exec_scope_) << "Duplicate PrepareWorkspace found"; + exec_scope_ = &scope_->NewScope(); + + for (auto var_desc : program.Block(0).AllVars()) { + if (!var_desc->Persistable()) { + auto* var = exec_scope_->Var(var_desc->Name()); + LOG(INFO) << "create tmp var " << var_desc->Name() << " " << var; + } + } + } + + // Build from a program and scope. + void Build(framework::ProgramDesc& program) { + CHECK(ops_.empty()) << "Executor duplicate Build found"; + + // Create operators. + for (auto* op_desc : program.Block(0).AllOps()) { + auto op_type = op_desc->Type(); + LOG(INFO) << "create Op [" << op_type << "]"; + ops_.emplace_back(LiteOpRegistry::Global().Create(op_type)); + // pick initial kernel + ops_.back()->PickKernel(valid_places_); + ops_.back()->Attach(*op_desc, exec_scope_); + } + } + + // Run the program. + void Run() { + for (auto& op : ops_) { + LOG(INFO) << op->DebugString(); + // TODO(Superjomn) check only once + op->CheckShape(); + op->InferShape(); + op->Run(); + } + } + + private: + std::vector> ops_; + lite::Scope* scope_{}; + std::vector valid_places_; + lite::Scope* exec_scope_{}; +}; + +} // namespace lite +} // namespace paddle diff --git a/paddle/fluid/lite/core/executor_test.cc b/paddle/fluid/lite/core/executor_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..c52b76555497ff0c658b74f9af6c2506eb2906a0 --- /dev/null +++ b/paddle/fluid/lite/core/executor_test.cc @@ -0,0 +1,65 @@ +// Copyright (c) 2019 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 "paddle/fluid/lite/core/executor.h" +#include +#include + +namespace paddle { +namespace lite { + +TEST(executor, test) { + std::vector valid_places{ + OpLite::Place{TARGET(kHost), PRECISION(kFloat)}}; + + Scope scope; + + Executor executor(&scope, valid_places); + + framework::ProgramDesc program; + program.MutableBlock(0)->Var("x"); + program.MutableBlock(0)->Var("bias")->SetPersistable(true); + program.MutableBlock(0)->Var("w")->SetPersistable(true); + program.MutableBlock(0)->Var("output"); + + auto& op_desc = *program.MutableBlock(0)->AppendOp(); + op_desc.SetType("fc"); + op_desc.SetInput("Input", {"x"}); + op_desc.SetInput("W", {"w"}); + op_desc.SetInput("Bias", {"bias"}); + op_desc.SetOutput("Out", {"output"}); + op_desc.SetAttr("in_num_col_dims", static_cast(1)); + program.Flush(); + + auto* w = scope.Var("w")->GetMutable(); + w->Resize({20, 20}); + auto* x = scope.Var("x")->GetMutable(); + x->Resize({1, 10, 20}); + auto* bias = scope.Var("bias")->GetMutable(); + bias->Resize({1, 20}); + + bias->mutable_data(); + w->mutable_data(); + x->mutable_data(); + + executor.PrepareWorkspace(program, &scope); + executor.Build(program); + executor.Run(); +} + +} // namespace lite +} // namespace paddle + +USE_LITE_OP(fc); +USE_LITE_KERNEL(fc, kHost, kFloat); diff --git a/paddle/fluid/lite/core/op_registry.h b/paddle/fluid/lite/core/op_registry.h index 2f1225925634663f738d5d69c0c5c0d5e9ed9b11..0821a355354bbdd9af9f8eb9dd7707e1fce88991 100644 --- a/paddle/fluid/lite/core/op_registry.h +++ b/paddle/fluid/lite/core/op_registry.h @@ -44,8 +44,8 @@ class OpLiteRegistor : public Registor { OpLiteRegistor(const std::string &op_type) : Registor([&] { LiteOpRegistry::Global().Register( - op_type, []() -> std::unique_ptr { - return std::unique_ptr(new OpClass); + op_type, [op_type]() -> std::unique_ptr { + return std::unique_ptr(new OpClass(op_type)); }); }) {} }; @@ -134,11 +134,15 @@ class KernelRegistor : public lite::Registor { #define LITE_OP_REGISTER_FAKE(op_type__) op_type__##__registry__ #define REGISTER_LITE_OP(op_type__, OpClass) \ static paddle::lite::OpLiteRegistor LITE_OP_REGISTER_INSTANCE( \ - op_type__)(#op_type__); + op_type__)(#op_type__); \ + int touch_op_##op_type__() { \ + return LITE_OP_REGISTER_INSTANCE(op_type__).Touch(); \ + } -#define USE_LITE_OP(op_type__) \ - int LITE_OP_REGISTER_FAKE(op_type__)((unused)) = \ - LITE_OP_REGISTER_INSTANCE(op_type__).Touch(); +#define USE_LITE_OP(op_type__) \ + extern int touch_op_##op_type__(); \ + int LITE_OP_REGISTER_FAKE(op_type__) __attribute__((unused)) = \ + touch_op_##op_type__(); // Kernel registry #define LITE_KERNEL_REGISTER(op_type__, target__, precision__) \ diff --git a/paddle/fluid/lite/kernels/host/CMakeLists.txt b/paddle/fluid/lite/kernels/host/CMakeLists.txt index ab297fefa82facb8d7a520a6b1f809d168865f81..0b1ed64263aa0af8f762809f3c8d132acd4c88d9 100644 --- a/paddle/fluid/lite/kernels/host/CMakeLists.txt +++ b/paddle/fluid/lite/kernels/host/CMakeLists.txt @@ -1,4 +1,8 @@ cc_library(fc_compute_host SRCS fc_compute.cc DEPS tensor_lite) cc_library(relu_compute_host SRCS relu_compute.cc DEPS tensor_lite) +cc_library(host_kernels DEPS + fc_compute_host + relu_compute_host) + cc_test(test_fc_compute SRCS fc_compute_test.cc DEPS fc_compute_host fc_op_lite) diff --git a/paddle/fluid/lite/kernels/host/fc_compute.h b/paddle/fluid/lite/kernels/host/fc_compute.h index 6daae48e7267a88eb3160dd6bb7fc0fc2c4d7766..3b79c5142727f69832fe4bfd09e58c5cbfa697c5 100644 --- a/paddle/fluid/lite/kernels/host/fc_compute.h +++ b/paddle/fluid/lite/kernels/host/fc_compute.h @@ -14,7 +14,6 @@ #pragma once #include "paddle/fluid/lite/core/kernel.h" -#include "paddle/fluid/lite/kernels/fc_compute.h" #include "paddle/fluid/lite/operators/fc_op.h" namespace paddle { diff --git a/paddle/fluid/lite/kernels/host/relu_compute.h b/paddle/fluid/lite/kernels/host/relu_compute.h index e4130e36097249c6e098017f5b6d471adcbf6bd4..486a1087879775b65d56c8dbdecd6398d56d4bb8 100644 --- a/paddle/fluid/lite/kernels/host/relu_compute.h +++ b/paddle/fluid/lite/kernels/host/relu_compute.h @@ -14,17 +14,33 @@ #pragma once #include "paddle/fluid/lite/core/kernel.h" +#include "paddle/fluid/lite/core/op_registry.h" namespace paddle { namespace lite { namespace kernels { namespace host { -class ReluCompute final : public OpKernel { +class ReluCompute : public OpKernel { public: + void Run() override { + auto& theparam = param(); + auto n = product(theparam.input->dims()); + const float* input = theparam.input->data(); + float* output = theparam.output->mutable_data(); + for (int i = 0; i < n; i++) { + output[i] = std::max(0.f, input[i]); + } + } + + TargetType target() const override { return TARGET(kHost); } + PrecisionType precision() const override { return PRECISION(kFloat); } }; } // namespace host } // namespace kernels } // namespace lite } // namespace paddle + +REGISTER_LITE_KERNEL(relu, kHost, kFloat, + paddle::lite::kernels::host::ReluCompute); diff --git a/paddle/fluid/lite/operators/CMakeLists.txt b/paddle/fluid/lite/operators/CMakeLists.txt index e13c2e61818cf4673abbe946e5a42174eedb53ec..7da1abd4e0b278d4ee6f1c058b9277e6dc6c77d7 100644 --- a/paddle/fluid/lite/operators/CMakeLists.txt +++ b/paddle/fluid/lite/operators/CMakeLists.txt @@ -1,5 +1,8 @@ cc_library(fc_op_lite SRCS fc_op.cc DEPS op_lite op_params_lite tensor_lite proto_desc) cc_library(relu_op_lite SRCS relu_op.cc DEPS op_lite) cc_library(op_params_lite SRCS op_params.cc DEPS tensor_lite) +cc_library(ops_lite DEPS + fc_op_lite + relu_op_lite) cc_test(test_fc_op_lite SRCS fc_op_test.cc DEPS fc_op_lite fc_compute_host) diff --git a/paddle/fluid/lite/operators/fc_op.cc b/paddle/fluid/lite/operators/fc_op.cc index ef0a1404ddb08cdc39ef7dae414b33a983633802..4d3d5506b10444fead07ccfc718a7d5d1b8c3a54 100644 --- a/paddle/fluid/lite/operators/fc_op.cc +++ b/paddle/fluid/lite/operators/fc_op.cc @@ -43,7 +43,7 @@ bool FcOpLite::CheckShape() const { static_cast(param_.in_num_col_dims)); param_.in_mat_dims = lite::flatten_to_2d(input_dims, param_.in_num_col_dims); - CHECK_EQ_OR_FALSE(param_.in_mat_dims[1], w_dims[0]); + // CHECK_EQ_OR_FALSE(param_.in_mat_dims[1], w_dims[0]); return true; } diff --git a/paddle/fluid/lite/operators/fc_op.h b/paddle/fluid/lite/operators/fc_op.h index 523d68c0ea157edf35479d6d152ae67dce9721d7..e3893cc938531c3755265f9b8af9e4ed9f65401f 100644 --- a/paddle/fluid/lite/operators/fc_op.h +++ b/paddle/fluid/lite/operators/fc_op.h @@ -35,11 +35,13 @@ class FcOpLite : public OpLite { bool InferShape() const override; + /* bool Run() override { CHECK(kernel_); kernel_->Run(); return true; } + */ // TODO(Superjomn) replace framework::OpDesc with a lite one. bool Attach(const framework::OpDesc &op_desc, lite::Scope *scope) override { @@ -51,10 +53,12 @@ class FcOpLite : public OpLite { param_.input = scope->FindVar(input)->GetMutable(); param_.w = scope->FindVar(W)->GetMutable(); param_.bias = scope->FindVar(bias)->GetMutable(); + CHECK(scope->FindVar(out)); param_.output = scope->FindVar(out)->GetMutable(); param_.in_num_col_dims = boost::get(op_desc.GetAttr("in_num_col_dims")); + CHECK(kernel_); kernel_->SetParam(param_); return true; diff --git a/paddle/fluid/lite/operators/op_params.h b/paddle/fluid/lite/operators/op_params.h index 972998154c3e8a4912b4823291d4bbc534675743..d701f5518c35b559b2c1126fbd00a8930028f2ba 100644 --- a/paddle/fluid/lite/operators/op_params.h +++ b/paddle/fluid/lite/operators/op_params.h @@ -25,7 +25,7 @@ namespace lite { namespace operators { struct FcParam { - Tensor* input{nullptr}; + Tensor* input{}; Tensor* w{}; Tensor* bias{}; Tensor* output{}; @@ -33,7 +33,12 @@ struct FcParam { int in_num_col_dims{0}; }; -using param_t = variant; +struct ReluParam { + Tensor* input{}; + Tensor* output{}; +}; + +using param_t = variant; } // namespace operators } // namespace lite diff --git a/paddle/fluid/lite/operators/relu_op.cc b/paddle/fluid/lite/operators/relu_op.cc index aac127d45cb899bd238b558c0c4d18308b6b6058..c46ccd9edea2afb8ad40dadd1fc3409eb4008c51 100644 --- a/paddle/fluid/lite/operators/relu_op.cc +++ b/paddle/fluid/lite/operators/relu_op.cc @@ -31,10 +31,15 @@ bool ReluOp::InferShape() const { return true; } -bool ReluOp::Run() { return false; } - -bool ReluOp::Attach(const framework::OpDesc &opdesc, framework::Scope *scope) { - return false; +bool ReluOp::Attach(const framework::OpDesc &opdesc, lite::Scope *scope) { + param_.input = const_cast( + &scope->FindVar(opdesc.Input("Input").front())->Get()); + param_.output = + scope->FindVar(opdesc.Output("Out").front())->GetMutable(); + CHECK(param_.input); + CHECK(param_.output); + kernel_->SetParam(param_); + return true; } REGISTER_LITE_OP(relu, ReluOp); diff --git a/paddle/fluid/lite/operators/relu_op.h b/paddle/fluid/lite/operators/relu_op.h index c24865593089acb43da6c8a1de6b383c536f152c..e7412d709cda6a913e5bc6e7eceb563d5060c385 100644 --- a/paddle/fluid/lite/operators/relu_op.h +++ b/paddle/fluid/lite/operators/relu_op.h @@ -15,6 +15,7 @@ #include #include #include "paddle/fluid/lite/core/op_lite.h" +#include "paddle/fluid/lite/core/scope.h" #include "paddle/fluid/lite/core/tensor.h" #include "paddle/fluid/lite/utils/all.h" @@ -22,27 +23,23 @@ namespace paddle { namespace lite { namespace operators { -struct ReluParam { - Tensor* input{nullptr}; - Tensor* output{nullptr}; -}; - class ReluOp : public OpLite { public: ReluOp() {} + ReluOp(const std::string &op_type) : OpLite(op_type) {} bool CheckShape() const override; bool InferShape() const override; - bool Run() override; - - bool Attach(const framework::OpDesc& opdesc, - framework::Scope* scope) override; + bool Attach(const framework::OpDesc &opdesc, lite::Scope *scope) override; std::string DebugString() const override { return "tanh"; } - void StaticPickKernel(const std::vector& valid_targets) override {} + void StaticPickKernel( + const std::vector &valid_targets) override { + kernel_ = std::move(CreateKernels(valid_targets).front()); + } private: mutable ReluParam param_;