| @@ -215,5 +215,26 @@ int GenerateInTensorC(const OpParameter *const parameter, const std::vector<lite | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| int CheckTensorsInvalid(const std::vector<Tensor *> &tensors) { | |||||
| for (auto &tensor : tensors) { | |||||
| if (tensor == nullptr) { | |||||
| MS_LOG(ERROR) << "check tensor is nullptr"; | |||||
| return RET_ERROR; | |||||
| } | |||||
| if (tensor->data_type() != kObjectTypeTensorType && tensor->data_c() == nullptr) { | |||||
| MS_LOG(ERROR) << "check tensor data is nullptr " << tensors; | |||||
| return RET_ERROR; | |||||
| } | |||||
| auto shape = tensor->shape(); | |||||
| bool valid = all_of(shape.begin(), shape.end(), [](int i) { return i >= 0; }); | |||||
| if (!valid) { | |||||
| MS_LOG(ERROR) << "The shape of tensor contains negative dimension," | |||||
| << "check the model and assign the input shape with method Resize()."; | |||||
| return RET_ERROR; | |||||
| } | |||||
| } | |||||
| return RET_OK; | |||||
| } | |||||
| } // namespace lite | } // namespace lite | ||||
| } // namespace mindspore | } // namespace mindspore | ||||
| @@ -39,6 +39,8 @@ int GenerateInTensorC(const OpParameter *const parameter, const std::vector<lite | |||||
| std::vector<lite::Tensor *> *outputs, std::vector<TensorC *> *in_tensor_c); | std::vector<lite::Tensor *> *outputs, std::vector<TensorC *> *in_tensor_c); | ||||
| int GenerateOutTensorC(const OpParameter *const parameter, const std::vector<lite::Tensor *> &inputs, | int GenerateOutTensorC(const OpParameter *const parameter, const std::vector<lite::Tensor *> &inputs, | ||||
| std::vector<lite::Tensor *> *outputs, std::vector<TensorC *> *out_tensor_c); | std::vector<lite::Tensor *> *outputs, std::vector<TensorC *> *out_tensor_c); | ||||
| int CheckTensorsInvalid(const std::vector<Tensor *> &tensors); | |||||
| } // namespace lite | } // namespace lite | ||||
| } // namespace mindspore | } // namespace mindspore | ||||
| @@ -17,34 +17,14 @@ | |||||
| #include "src/executor.h" | #include "src/executor.h" | ||||
| #include <queue> | #include <queue> | ||||
| #include "include/errorcode.h" | #include "include/errorcode.h" | ||||
| #include "src/common/tensor_util.h" | |||||
| namespace mindspore::lite { | namespace mindspore::lite { | ||||
| int Executor::CheckInputs(const std::vector<Tensor *> &in_tensors) { | |||||
| for (auto &inTensor : in_tensors) { | |||||
| if (inTensor == nullptr) { | |||||
| MS_LOG(ERROR) << "Graph input tensor is nullptr"; | |||||
| return RET_ERROR; | |||||
| } | |||||
| if (inTensor->data_type() != kObjectTypeTensorType && inTensor->data_c() == nullptr) { | |||||
| MS_LOG(ERROR) << "Graph input tensor data is nullptr " << in_tensors; | |||||
| return RET_ERROR; | |||||
| } | |||||
| auto shape = inTensor->shape(); | |||||
| bool valid = all_of(shape.begin(), shape.end(), [](int i) { return i >= 0; }); | |||||
| if (!valid) { | |||||
| MS_LOG(ERROR) << "The shape of input tensor contains negative dimension," | |||||
| << "check the model and assign the input shape with method Resize()."; | |||||
| return RET_ERROR; | |||||
| } | |||||
| } | |||||
| return RET_OK; | |||||
| } | |||||
| int Executor::Run(const std::vector<Tensor *> &in_tensors, const std::vector<Tensor *> &out_tensors, | int Executor::Run(const std::vector<Tensor *> &in_tensors, const std::vector<Tensor *> &out_tensors, | ||||
| const std::vector<kernel::LiteKernel *> &kernels, mindspore::Allocator *allocator, | const std::vector<kernel::LiteKernel *> &kernels, mindspore::Allocator *allocator, | ||||
| const KernelCallBack &before, const KernelCallBack &after) { | const KernelCallBack &before, const KernelCallBack &after) { | ||||
| MS_ASSERT(nullptr != allocator); | MS_ASSERT(nullptr != allocator); | ||||
| auto ret = this->CheckInputs(in_tensors); | |||||
| auto ret = CheckTensorsInvalid(in_tensors); | |||||
| if (RET_OK != ret) { | if (RET_OK != ret) { | ||||
| MS_LOG(ERROR) << "CheckInputs failed"; | MS_LOG(ERROR) << "CheckInputs failed"; | ||||
| return ret; | return ret; | ||||
| @@ -88,42 +68,4 @@ int Executor::Run(const std::vector<Tensor *> &in_tensors, const std::vector<Ten | |||||
| } | } | ||||
| return RET_OK; | return RET_OK; | ||||
| } | } | ||||
| int CpuExecutor::Run(const std::vector<Tensor *> &in_tensors, const std::vector<Tensor *> &out_tensors, | |||||
| const std::vector<kernel::LiteKernel *> &kernels, Allocator *allocator, | |||||
| const KernelCallBack &before, const KernelCallBack &after) { | |||||
| MS_ASSERT(nullptr != allocator); | |||||
| // not check input for merge. too hard | |||||
| if (kernels.front()->Type() != schema::PrimitiveType_Merge) { | |||||
| auto ret = this->CheckInputs(in_tensors); | |||||
| if (ret != RET_OK) { | |||||
| MS_LOG(ERROR) << "CheckInputs failed"; | |||||
| return ret; | |||||
| } | |||||
| } | |||||
| #ifdef SUPPORT_TRAIN | |||||
| for (auto out_tensor : out_tensors) { // increase RefCount of output tensors, such that Run will not free them | |||||
| out_tensor->set_ref_count(out_tensor->ref_count() + 1); | |||||
| } | |||||
| #endif | |||||
| for (auto *kernel : kernels) { | |||||
| MS_ASSERT(nullptr != kernel); | |||||
| auto ret = kernel->PreProcess(); | |||||
| if (RET_OK != ret) { | |||||
| MS_LOG(ERROR) << "PreProcess kernel failed, name: " << kernel->name(); | |||||
| return ret; | |||||
| } | |||||
| ret = kernel->Run(before, after); | |||||
| if (RET_OK != ret) { | |||||
| MS_LOG(ERROR) << "run kernel failed, name: " << kernel->name(); | |||||
| return ret; | |||||
| } | |||||
| ret = kernel->PostProcess(); | |||||
| if (RET_OK != ret) { | |||||
| MS_LOG(ERROR) << "PostProcess kernel failed, name: " << kernel->name(); | |||||
| return ret; | |||||
| } | |||||
| } | |||||
| return RET_OK; | |||||
| } | |||||
| } // namespace mindspore::lite | } // namespace mindspore::lite | ||||
| @@ -33,20 +33,6 @@ class Executor { | |||||
| virtual int Run(const std::vector<Tensor *> &in_tensors, const std::vector<Tensor *> &out_tensors, | virtual int Run(const std::vector<Tensor *> &in_tensors, const std::vector<Tensor *> &out_tensors, | ||||
| const std::vector<kernel::LiteKernel *> &kernels, mindspore::Allocator *allocator = nullptr, | const std::vector<kernel::LiteKernel *> &kernels, mindspore::Allocator *allocator = nullptr, | ||||
| const KernelCallBack &before = nullptr, const KernelCallBack &after = nullptr); | const KernelCallBack &before = nullptr, const KernelCallBack &after = nullptr); | ||||
| protected: | |||||
| static int CheckInputs(const std::vector<Tensor *> &in_tensors); | |||||
| }; | |||||
| class CpuExecutor : public Executor { | |||||
| public: | |||||
| CpuExecutor() = default; | |||||
| virtual ~CpuExecutor() = default; | |||||
| int Run(const std::vector<Tensor *> &in_tensors, const std::vector<Tensor *> &out_tensors, | |||||
| const std::vector<kernel::LiteKernel *> &kernels, mindspore::Allocator *allocator = nullptr, | |||||
| const KernelCallBack &before = nullptr, const KernelCallBack &after = nullptr) override; | |||||
| }; | }; | ||||
| } // namespace mindspore::lite | } // namespace mindspore::lite | ||||
| #endif | #endif | ||||
| @@ -18,6 +18,7 @@ | |||||
| #include "src/mindrt_executor.h" | #include "src/mindrt_executor.h" | ||||
| #include "src/lite_mindrt.h" | #include "src/lite_mindrt.h" | ||||
| #include "include/errorcode.h" | #include "include/errorcode.h" | ||||
| #include "src/common/tensor_util.h" | |||||
| namespace mindspore::lite { | namespace mindspore::lite { | ||||
| @@ -62,7 +63,7 @@ int MindrtExecutor::Run(const std::vector<Tensor *> &in_tensors, const std::vect | |||||
| const KernelCallBack &before, const KernelCallBack &after) { | const KernelCallBack &before, const KernelCallBack &after) { | ||||
| MS_ASSERT(nullptr != allocator); | MS_ASSERT(nullptr != allocator); | ||||
| if (kernels.front()->Type() != schema::PrimitiveType_Merge) { | if (kernels.front()->Type() != schema::PrimitiveType_Merge) { | ||||
| auto ret = this->CheckInputs(in_tensors); | |||||
| auto ret = CheckTensorsInvalid(in_tensors); | |||||
| if (RET_OK != ret) { | if (RET_OK != ret) { | ||||
| MS_LOG(ERROR) << "CheckInputs failed"; | MS_LOG(ERROR) << "CheckInputs failed"; | ||||
| return ret; | return ret; | ||||
| @@ -22,6 +22,7 @@ | |||||
| #endif | #endif | ||||
| #include "src/common/version_manager.h" | #include "src/common/version_manager.h" | ||||
| #include "src/runtime/infer_manager.h" | #include "src/runtime/infer_manager.h" | ||||
| #include "src/common/tensor_util.h" | |||||
| namespace mindspore::kernel { | namespace mindspore::kernel { | ||||
| using mindspore::lite::RET_ERROR; | using mindspore::lite::RET_ERROR; | ||||
| @@ -70,19 +71,6 @@ std::string SubGraphKernel::ToString() const { | |||||
| return oss.str(); | return oss.str(); | ||||
| } | } | ||||
| int SubGraphKernel::Run() { | |||||
| if (this->executor_ == nullptr) { | |||||
| MS_LOG(ERROR) << "executor is nullptr"; | |||||
| return RET_ERROR; | |||||
| } | |||||
| auto ret = executor_->Run(this->in_tensors_, this->out_tensors_, this->nodes_, this->context_->allocator.get()); | |||||
| if (ret != RET_OK) { | |||||
| MS_LOG(ERROR) << "Run sub graph failed: " << ret; | |||||
| return ret; | |||||
| } | |||||
| return RET_OK; | |||||
| } | |||||
| int SubGraphKernel::Run(const KernelCallBack &before, const KernelCallBack &after) { | int SubGraphKernel::Run(const KernelCallBack &before, const KernelCallBack &after) { | ||||
| if (this->executor_ == nullptr) { | if (this->executor_ == nullptr) { | ||||
| MS_LOG(ERROR) << "executor is nullptr"; | MS_LOG(ERROR) << "executor is nullptr"; | ||||
| @@ -165,15 +153,42 @@ int CpuSubGraph::Prepare() { | |||||
| tensor->set_allocator(this->context_->allocator.get()); | tensor->set_allocator(this->context_->allocator.get()); | ||||
| } | } | ||||
| } | } | ||||
| this->executor_ = new (std::nothrow) mindspore::lite::CpuExecutor; | |||||
| if (this->executor_ == nullptr) { | |||||
| MS_LOG(ERROR) << "new CpuExecutor failed"; | |||||
| return RET_ERROR; | |||||
| return RET_OK; | |||||
| } | |||||
| int CpuSubGraph::Run(const KernelCallBack &before, const KernelCallBack &after) { | |||||
| MS_ASSERT(nullptr != this->context_->allocator.get()); | |||||
| if (nodes_.front()->Type() != schema::PrimitiveType_Merge) { | |||||
| auto ret = CheckTensorsInvalid(in_tensors_); | |||||
| if (ret != RET_OK) { | |||||
| MS_LOG(ERROR) << "CheckInputs failed"; | |||||
| return ret; | |||||
| } | |||||
| } | } | ||||
| ret = this->executor_->Prepare(this->nodes_); | |||||
| if (ret != RET_OK) { | |||||
| MS_LOG(ERROR) << "Prepare CpuExecutor failed"; | |||||
| return ret; | |||||
| #ifdef SUPPORT_TRAIN | |||||
| for (auto out_tensor : out_tensors_) { // increase RefCount of output tensors, such that Run will not free them | |||||
| out_tensor->set_ref_count(out_tensor->ref_count() + 1); | |||||
| } | |||||
| #endif | |||||
| for (auto *kernel : nodes_) { | |||||
| MS_ASSERT(nullptr != kernel); | |||||
| auto ret = kernel->PreProcess(); | |||||
| if (RET_OK != ret) { | |||||
| MS_LOG(ERROR) << "PreProcess kernel failed, name: " << kernel->name(); | |||||
| return ret; | |||||
| } | |||||
| ret = kernel->Run(before, after); | |||||
| if (RET_OK != ret) { | |||||
| MS_LOG(ERROR) << "run kernel failed, name: " << kernel->name(); | |||||
| return ret; | |||||
| } | |||||
| ret = kernel->PostProcess(); | |||||
| if (RET_OK != ret) { | |||||
| MS_LOG(ERROR) << "PostProcess kernel failed, name: " << kernel->name(); | |||||
| return ret; | |||||
| } | |||||
| } | } | ||||
| return RET_OK; | return RET_OK; | ||||
| } | } | ||||
| @@ -94,7 +94,7 @@ class SubGraphKernel : public LiteKernel { | |||||
| // called before Run | // called before Run | ||||
| int PreProcess() override { return mindspore::lite::RET_OK; } | int PreProcess() override { return mindspore::lite::RET_OK; } | ||||
| int Run() override; | |||||
| int Run() override { return Run(nullptr, nullptr); } | |||||
| int Run(const KernelCallBack &before, const KernelCallBack &after) override; | int Run(const KernelCallBack &before, const KernelCallBack &after) override; | ||||
| // called after Run | // called after Run | ||||
| @@ -134,10 +134,8 @@ class CpuSubGraph : public SubGraphKernel { | |||||
| int Prepare() override; | int Prepare() override; | ||||
| int Init() override { return SubGraphKernel::Init(); } | int Init() override { return SubGraphKernel::Init(); } | ||||
| int PreProcess() override { return SubGraphKernel::PreProcess(); } | int PreProcess() override { return SubGraphKernel::PreProcess(); } | ||||
| int Run() override { return SubGraphKernel::Run(); } | |||||
| int Run(const KernelCallBack &before, const KernelCallBack &after) override { | |||||
| return SubGraphKernel::Run(before, after); | |||||
| }; | |||||
| int Run() override { return Run(nullptr, nullptr); } | |||||
| int Run(const KernelCallBack &before, const KernelCallBack &after) override; | |||||
| int PostProcess() override { return SubGraphKernel::PostProcess(); } | int PostProcess() override { return SubGraphKernel::PostProcess(); } | ||||
| }; | }; | ||||
| @@ -35,6 +35,7 @@ | |||||
| #include "src/kernel_registry.h" | #include "src/kernel_registry.h" | ||||
| #include "src/runtime/kernel/arm/fp32_grad/convolution.h" | #include "src/runtime/kernel/arm/fp32_grad/convolution.h" | ||||
| #include "src/runtime/kernel/arm/fp32/batchnorm_fp32.h" | #include "src/runtime/kernel/arm/fp32/batchnorm_fp32.h" | ||||
| #include "src/common/tensor_util.h" | |||||
| namespace mindspore { | namespace mindspore { | ||||
| namespace lite { | namespace lite { | ||||
| @@ -188,17 +189,33 @@ int TrainSession::RunGraph(const KernelCallBack &before, const KernelCallBack &a | |||||
| return lite::RET_NULL_PTR; | return lite::RET_NULL_PTR; | ||||
| } | } | ||||
| auto run_kernel = (train_mode_) ? train_kernels_ : inference_kernels_; | auto run_kernel = (train_mode_) ? train_kernels_ : inference_kernels_; | ||||
| lite::CpuExecutor executor; | |||||
| auto ret = RET_OK; | |||||
| if (before == nullptr && after == nullptr) { | |||||
| ret = executor.Run(this->inputs_, this->outputs_, run_kernel, this->context_->allocator.get()); | |||||
| } else { | |||||
| ret = executor.Run(this->inputs_, this->outputs_, run_kernel, this->context_->allocator.get(), before, after); | |||||
| } | |||||
| auto ret = CheckTensorsInvalid(inputs_); | |||||
| if (ret != RET_OK) { | if (ret != RET_OK) { | ||||
| MS_LOG(ERROR) << "failed to run model"; | |||||
| MS_LOG(ERROR) << "CheckInputs failed"; | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| for (auto out_tensor : outputs_) { // increase RefCount of output tensors, such that Run will not free them | |||||
| out_tensor->set_ref_count(out_tensor->ref_count() + 1); | |||||
| } | |||||
| for (auto *kernel : run_kernel) { | |||||
| MS_ASSERT(nullptr != kernel); | |||||
| ret = kernel->PreProcess(); | |||||
| if (RET_OK != ret) { | |||||
| MS_LOG(ERROR) << "PreProcess kernel failed, name: " << kernel->name(); | |||||
| return ret; | |||||
| } | |||||
| ret = kernel->Run(before, after); | |||||
| if (RET_OK != ret) { | |||||
| MS_LOG(ERROR) << "run kernel failed, name: " << kernel->name(); | |||||
| return ret; | |||||
| } | |||||
| ret = kernel->PostProcess(); | |||||
| if (RET_OK != ret) { | |||||
| MS_LOG(ERROR) << "PostProcess kernel failed, name: " << kernel->name(); | |||||
| return ret; | |||||
| } | |||||
| } | |||||
| if (train_mode_ && virtual_batch_multiplier_) { | if (train_mode_ && virtual_batch_multiplier_) { | ||||
| virtual_batch_idx_++; | virtual_batch_idx_++; | ||||