optimize model

pull/5772/head
chenjianping 4 years ago
parent 77dd91a646
commit 94b1e4e09b

@ -0,0 +1,29 @@
/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* 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.
*/
#ifndef MINDSPORE_LITE_INCLUDE_LITE_UTILS_H_
#define MINDSPORE_LITE_INCLUDE_LITE_UTILS_H_
#include <vector>
#include <string>
#include "schema/model_generated.h"
namespace mindspore::lite {
using TensorPtrVector = std::vector<mindspore::schema::Tensor *>;
using Uint32Vector = std::vector<uint32_t>;
using String = std::string;
using NodeType = schema::NodeType;
} // namespace mindspore::lite
#endif // MINDSPORE_LITE_INCLUDE_LITE_UTILS_H_

@ -13,32 +13,30 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#ifndef MINDSPORE_LITE_INCLUDE_MODEL_H #ifndef MINDSPORE_LITE_INCLUDE_MODEL_H
#define MINDSPORE_LITE_INCLUDE_MODEL_H #define MINDSPORE_LITE_INCLUDE_MODEL_H
#include <string>
#include <vector> #include <vector>
#include <memory> #include "include/lite_utils.h"
#include "schema/model_generated.h"
namespace mindspore {
#define MS_API __attribute__((visibility("default")))
namespace lite {
/// \brief ModelImpl defined the implement class of Model in MindSpore Lite.
///
/// \note List public class and interface for reference.
class ModelImpl;
/// \brief Primitive defined as prototype of operator. namespace mindspore::lite {
///
/// \note List public class and interface for reference.
class PrimitiveC; class PrimitiveC;
struct Model {
struct Node {
String name_;
NodeType node_type_;
PrimitiveC *primitive_;
Uint32Vector input_indices_;
Uint32Vector output_indices_;
};
using NodePtrVector = std::vector<Node *>;
String name_;
String version_;
TensorPtrVector all_tensors_;
Uint32Vector input_indices_;
Uint32Vector output_indices_;
NodePtrVector nodes_;
char *buf;
/// \brief Model defined model in MindSpore Lite for managing graph.
class MS_API Model {
public:
/// \brief Static method to create a Model pointer. /// \brief Static method to create a Model pointer.
/// ///
/// \param[in] model_buf Define the buffer read from a model file. /// \param[in] model_buf Define the buffer read from a model file.
@ -47,65 +45,9 @@ class MS_API Model {
/// \return Pointer of MindSpore Lite Model. /// \return Pointer of MindSpore Lite Model.
static Model *Import(const char *model_buf, size_t size); static Model *Import(const char *model_buf, size_t size);
/// \brief Constructor of MindSpore Lite Model using default value for parameters. /// \brief Free all the temporary buffer
/// void Free();
/// \return Instance of MindSpore Lite Model.
Model() = default;
/// \brief Destructor of MindSpore Lite Model.
virtual ~Model();
/// \brief Get MindSpore Lite Primitive by name.
///
/// \param[in] name Define name of primitive to be returned.
///
/// \return the pointer of MindSpore Lite Primitive.
PrimitiveC *GetOp(const std::string &name) const;
/// \brief Get graph defined in flatbuffers.
///
/// \return the pointer of graph defined in flatbuffers.
const schema::MetaGraph *GetMetaGraph() const;
/// \brief Free MetaGraph in MindSpore Lite Model.
void FreeMetaGraph();
ModelImpl *model_impl() {return model_impl_;}
protected:
ModelImpl *model_impl_ = nullptr;
};
/// \brief ModelBuilder defined by MindSpore Lite.
class MS_API ModelBuilder {
public:
/// \brief OutEdge defined by MindSpore Lite.
struct OutEdge {
std::string nodeId; /**< ID of a node linked by this edge */
size_t outEdgeIndex; /**< Index of this edge */
};
/// \brief Constructor of MindSpore Lite Model using default value for parameters.
///
/// \return Instance of MindSpore Lite ModelBuilder.
ModelBuilder() = default;
/// \brief Destructor of MindSpore Lite ModelBuilder.
virtual ~ModelBuilder() = default;
/// \brief Add primitive into model builder for model building.
///
/// \param[in] op Define the primitive to be added.
/// \param[in] inputs Define input edge of primitive to be added.
///
/// \return ID of the added primitive.
virtual std::string AddOp(const PrimitiveC &op, const std::vector<OutEdge> &inputs) = 0;
/// \brief Finish constructing the model.
///
/// \return the pointer of MindSpore Lite Model.
virtual Model *Construct();
}; };
} // namespace lite } // namespace mindspore::lite
} // namespace mindspore
#endif // MINDSPORE_LITE_INCLUDE_MODEL_H #endif // MINDSPORE_LITE_INCLUDE_MODEL_H

@ -24,15 +24,15 @@
namespace mindspore { namespace mindspore {
namespace lite { namespace lite {
std::vector<size_t> GetGraphInputNodes(const schema::MetaGraph *meta_graph) { std::vector<size_t> GetGraphInputNodes(const lite::Model *model) {
MS_ASSERT(nullptr != meta_graph); MS_ASSERT(model != nullptr);
std::vector<size_t> ret; std::vector<size_t> ret;
for (auto graph_in_index : *(meta_graph->inputIndex())) { for (auto graph_in_index : model->input_indices_) {
for (size_t j = 0; j < meta_graph->nodes()->size(); j++) { auto node_size = model->nodes_.size();
auto *cNode = meta_graph->nodes()->GetAs<schema::CNode>(j); for (size_t j = 0; j < node_size; ++j) {
MS_ASSERT(nullptr != cNode); auto node = model->nodes_[j];
MS_ASSERT(nullptr != cNode->inputIndex()); MS_ASSERT(node != nullptr);
if (std::any_of(cNode->inputIndex()->begin(), cNode->inputIndex()->end(), if (std::any_of(node->input_indices_.begin(), node->input_indices_.end(),
[&](const uint32_t &node_in_index) { return node_in_index == graph_in_index; })) { [&](const uint32_t &node_in_index) { return node_in_index == graph_in_index; })) {
if (!IsContain<size_t>(ret, j)) { if (!IsContain<size_t>(ret, j)) {
ret.emplace_back(j); ret.emplace_back(j);
@ -43,15 +43,15 @@ std::vector<size_t> GetGraphInputNodes(const schema::MetaGraph *meta_graph) {
return ret; return ret;
} }
std::vector<size_t> GetGraphOutputNodes(const schema::MetaGraph *meta_graph) { std::vector<size_t> GetGraphOutputNodes(const lite::Model *model) {
MS_ASSERT(nullptr != meta_graph); MS_ASSERT(model != nullptr);
std::vector<size_t> ret; std::vector<size_t> ret;
for (auto graph_out_index : *(meta_graph->outputIndex())) { for (auto graph_out_index : model->output_indices_) {
for (size_t j = 0; j < meta_graph->nodes()->size(); j++) { auto node_size = model->nodes_.size();
auto *cNode = meta_graph->nodes()->GetAs<schema::CNode>(j); for (size_t j = 0; j < node_size; ++j) {
MS_ASSERT(nullptr != cNode); auto node = model->nodes_[j];
MS_ASSERT(nullptr != cNode->outputIndex()); MS_ASSERT(node != nullptr);
if (std::any_of(cNode->outputIndex()->begin(), cNode->outputIndex()->end(), if (std::any_of(node->output_indices_.begin(), node->output_indices_.end(),
[&](const uint32_t &node_out_index) { return node_out_index == graph_out_index; })) { [&](const uint32_t &node_out_index) { return node_out_index == graph_out_index; })) {
if (!IsContain<size_t>(ret, j)) { if (!IsContain<size_t>(ret, j)) {
ret.emplace_back(j); ret.emplace_back(j);
@ -62,15 +62,17 @@ std::vector<size_t> GetGraphOutputNodes(const schema::MetaGraph *meta_graph) {
return ret; return ret;
} }
std::vector<size_t> GetLinkedPostNodeIdx(const schema::MetaGraph &graph, const size_t &tensor_idx) { std::vector<size_t> GetLinkedPostNodeIdx(const lite::Model *model, const size_t tensor_idx) {
MS_ASSERT(model != nullptr);
std::vector<size_t> post_node_idxes; std::vector<size_t> post_node_idxes;
for (size_t i = 0; i < graph.nodes()->size(); i++) { auto nodes_size = model->nodes_.size();
auto node = graph.nodes()->GetAs<schema::CNode>(i); for (size_t i = 0; i < nodes_size; ++i) {
auto node = model->nodes_[i];
if (node == nullptr) { if (node == nullptr) {
continue; continue;
} }
auto node_input_idxes = node->inputIndex();
auto is_contain = std::any_of(node_input_idxes->begin(), node_input_idxes->end(), auto is_contain = std::any_of(node->input_indices_.begin(), node->input_indices_.end(),
[&](const uint32_t &node_input_idx) { return node_input_idx == tensor_idx; }); [&](const uint32_t &node_input_idx) { return node_input_idx == tensor_idx; });
if (is_contain) { if (is_contain) {
post_node_idxes.emplace_back(i); post_node_idxes.emplace_back(i);

@ -25,16 +25,17 @@
#include "schema/model_generated.h" #include "schema/model_generated.h"
#include "utils//log_adapter.h" #include "utils//log_adapter.h"
#include "include/errorcode.h" #include "include/errorcode.h"
#include "include/model.h"
namespace mindspore { namespace mindspore {
namespace lite { namespace lite {
using NODE_ID = std::string; using NODE_ID = std::string;
std::vector<size_t> GetGraphInputNodes(const schema::MetaGraph *meta_graph); std::vector<size_t> GetGraphInputNodes(const lite::Model *model);
std::vector<size_t> GetGraphOutputNodes(const schema::MetaGraph *meta_graph); std::vector<size_t> GetGraphOutputNodes(const lite::Model *model);
std::vector<size_t> GetLinkedPostNodeIdx(const schema::MetaGraph &graph, const size_t &tensor_idx); std::vector<size_t> GetLinkedPostNodeIdx(const lite::Model *model, const size_t tensor_idx);
} // namespace lite } // namespace lite
} // namespace mindspore } // namespace mindspore

@ -32,6 +32,7 @@
namespace mindspore { namespace mindspore {
namespace lite { namespace lite {
static std::vector<schema::PrimitiveType> packed_op = { static std::vector<schema::PrimitiveType> packed_op = {
schema::PrimitiveType_Conv2D, schema::PrimitiveType_DeConv2D, schema::PrimitiveType_Conv2D, schema::PrimitiveType_DeConv2D,
schema::PrimitiveType_DepthwiseConv2D, schema::PrimitiveType_DeDepthwiseConv2D, schema::PrimitiveType_DepthwiseConv2D, schema::PrimitiveType_DeDepthwiseConv2D,
@ -39,27 +40,23 @@ static std::vector<schema::PrimitiveType> packed_op = {
// this method will not check whether tensor_idx is a weight tensor index, caller should ensure this. // this method will not check whether tensor_idx is a weight tensor index, caller should ensure this.
static bool WeightTensorNeedCopy(const lite::Model *model, const uint32_t tensor_idx) { static bool WeightTensorNeedCopy(const lite::Model *model, const uint32_t tensor_idx) {
MS_ASSERT(nullptr != model); MS_ASSERT(model != nullptr);
auto meta_graph = model->GetMetaGraph(); auto post_node_idxes = GetLinkedPostNodeIdx(model, tensor_idx);
MS_ASSERT(nullptr != meta_graph);
auto post_node_idxes = GetLinkedPostNodeIdx(*meta_graph, tensor_idx);
return std::none_of(post_node_idxes.begin(), post_node_idxes.end(), [&](const size_t &post_node_idx) { return std::none_of(post_node_idxes.begin(), post_node_idxes.end(), [&](const size_t &post_node_idx) {
auto cNode = meta_graph->nodes()->GetAs<schema::CNode>(post_node_idx); auto node = model->nodes_[post_node_idx];
MS_ASSERT(cNode != nullptr); MS_ASSERT(node != nullptr);
return IsContain(packed_op, cNode->primitive()->value_type()); return IsContain(packed_op, static_cast<schema::PrimitiveType>(node->primitive_->Type()));
}); });
} }
int LiteSession::ConvertTensors(const lite::Model *model) { int LiteSession::ConvertTensors(const lite::Model *model) {
MS_ASSERT(nullptr != model); MS_ASSERT(model != nullptr);
auto meta_graph = model->GetMetaGraph();
MS_ASSERT(nullptr != meta_graph);
copyed_tensor_idxes_.clear(); copyed_tensor_idxes_.clear();
uint32_t tensorCount = meta_graph->allTensors()->size(); uint32_t tensor_count = model->all_tensors_.size();
for (uint32_t i = 0; i < tensorCount; i++) { for (uint32_t i = 0; i < tensor_count; ++i) {
auto *srcTensor = meta_graph->allTensors()->GetAs<schema::Tensor>(i); auto *srcTensor = model->all_tensors_[i];
if (srcTensor == nullptr) { if (srcTensor == nullptr) {
MS_LOG(ERROR) << i << "th tensor in meta_graph is nullptr"; MS_LOG(ERROR) << i << "th tensor in model is nullptr";
return RET_NULL_PTR; return RET_NULL_PTR;
} }
std::vector<int> shape; std::vector<int> shape;
@ -115,11 +112,9 @@ int LiteSession::ConvertTensors(const lite::Model *model) {
void LiteSession::InitGraphInputTensors(const lite::Model *model) { void LiteSession::InitGraphInputTensors(const lite::Model *model) {
MS_ASSERT(model != nullptr); MS_ASSERT(model != nullptr);
auto meta_graph = model->GetMetaGraph(); auto graph_in_size = model->input_indices_.size();
MS_ASSERT(this->inputs_.empty()); for (size_t i = 0; i < graph_in_size; ++i) {
MS_ASSERT(meta_graph != nullptr); auto in_tensor_idx = model->input_indices_[i];
for (size_t i = 0; i < meta_graph->inputIndex()->size(); i++) {
auto in_tensor_idx = size_t(meta_graph->inputIndex()->GetAs<uint32_t>(i));
MS_ASSERT(in_tensor_idx < this->tensors_.size()); MS_ASSERT(in_tensor_idx < this->tensors_.size());
auto *in_tensor = this->tensors_.at(in_tensor_idx); auto *in_tensor = this->tensors_.at(in_tensor_idx);
MS_ASSERT(in_tensor != nullptr); MS_ASSERT(in_tensor != nullptr);
@ -137,11 +132,11 @@ void LiteSession::InitGraphInputMSTensors() {
void LiteSession::InitGraphOutputTensors(const lite::Model *model) { void LiteSession::InitGraphOutputTensors(const lite::Model *model) {
MS_ASSERT(model != nullptr); MS_ASSERT(model != nullptr);
auto meta_graph = model->GetMetaGraph();
MS_ASSERT(this->outputs_.empty()); MS_ASSERT(this->outputs_.empty());
MS_ASSERT(meta_graph != nullptr); MS_ASSERT(meta_graph != nullptr);
for (size_t i = 0; i < meta_graph->outputIndex()->size(); i++) { auto graph_out_size = model->output_indices_.size();
auto out_tensor_idx = size_t(meta_graph->outputIndex()->GetAs<uint32_t>(i)); for (size_t i = 0; i < graph_out_size; ++i) {
auto out_tensor_idx = model->output_indices_[i];
MS_ASSERT(out_tensor_idx < this->tensors_.size()); MS_ASSERT(out_tensor_idx < this->tensors_.size());
auto *out_tensor = this->tensors_.at(out_tensor_idx); auto *out_tensor = this->tensors_.at(out_tensor_idx);
MS_ASSERT(out_tensor != nullptr); MS_ASSERT(out_tensor != nullptr);
@ -151,19 +146,19 @@ void LiteSession::InitGraphOutputTensors(const lite::Model *model) {
void LiteSession::InitGraphInputMap(const lite::Model *model) { void LiteSession::InitGraphInputMap(const lite::Model *model) {
MS_ASSERT(model != nullptr); MS_ASSERT(model != nullptr);
auto meta_graph = model->GetMetaGraph();
MS_ASSERT(this->input_map_.empty()); MS_ASSERT(this->input_map_.empty());
MS_ASSERT(meta_graph != nullptr); auto graph_input_node_indexes = GetGraphInputNodes(model);
auto graph_input_node_indexes = GetGraphInputNodes(meta_graph); auto graph_in_size = model->input_indices_.size();
for (auto in_node_index : graph_input_node_indexes) { for (auto in_node_index : graph_input_node_indexes) {
auto *in_node = meta_graph->nodes()->GetAs<schema::CNode>(in_node_index); auto in_node = model->nodes_[in_node_index];
MS_ASSERT(nullptr != in_node); MS_ASSERT(in_node != nullptr);
MS_ASSERT(this->input_map_.find(in_node->name()->str()) == this->input_map_.end()); MS_ASSERT(this->input_map_.find(in_node->name()->str()) == this->input_map_.end());
for (size_t i = 0; i < in_node->inputIndex()->size(); i++) { auto in_size = in_node->input_indices_.size();
auto in_tensor_index = size_t(in_node->inputIndex()->GetAs<uint32_t>(i)); for (size_t i = 0; i < in_size; ++i) {
auto in_tensor_index = size_t(in_node->input_indices_[i]);
bool is_graph_input = false; bool is_graph_input = false;
for (size_t j = 0; j < meta_graph->inputIndex()->size(); j++) { for (size_t j = 0; j < graph_in_size; ++j) {
if (in_tensor_index == size_t(meta_graph->inputIndex()->GetAs<uint32_t>(j))) { if (in_tensor_index == model->input_indices_[j]) {
is_graph_input = true; is_graph_input = true;
break; break;
} }
@ -174,28 +169,30 @@ void LiteSession::InitGraphInputMap(const lite::Model *model) {
MS_ASSERT(in_tensor_index < this->tensors_.size()); MS_ASSERT(in_tensor_index < this->tensors_.size());
auto *in_tensor = this->tensors_.at(in_tensor_index); auto *in_tensor = this->tensors_.at(in_tensor_index);
MS_ASSERT(in_tensor != nullptr); MS_ASSERT(in_tensor != nullptr);
auto *ms_tensor = new tensor::LiteTensor(in_tensor); auto *ms_tensor = new (std::nothrow) tensor::LiteTensor(in_tensor);
MS_ASSERT(nullptr != ms_tensor); if (ms_tensor == nullptr) {
this->input_map_[in_node->name()->str()].emplace_back(ms_tensor); MS_LOG(ERROR) << "new lite tensor fail!";
return;
}
this->input_map_[in_node->name_].emplace_back(ms_tensor);
} }
} }
} }
void LiteSession::InitGraphOutputNodeMap(const lite::Model *model) { void LiteSession::InitGraphOutputNodeMap(const lite::Model *model) {
MS_ASSERT(model != nullptr); MS_ASSERT(model != nullptr);
auto meta_graph = model->GetMetaGraph(); auto graph_output_node_indexes = GetGraphOutputNodes(model);
MS_ASSERT(this->output_node_map_.empty()); auto graph_out_size = model->output_indices_.size();
MS_ASSERT(meta_graph != nullptr);
auto graph_output_node_indexes = GetGraphOutputNodes(meta_graph);
for (auto out_node_index : graph_output_node_indexes) { for (auto out_node_index : graph_output_node_indexes) {
auto *out_node = meta_graph->nodes()->GetAs<schema::CNode>(out_node_index); auto out_node = model->nodes_[out_node_index];
MS_ASSERT(nullptr != out_node); MS_ASSERT(out_node != nullptr);
MS_ASSERT(this->output_map_.find(out_node->name()->str()) == this->output_map_.end()); MS_ASSERT(this->output_map_.find(out_node->name()->str()) == this->output_map_.end());
for (size_t i = 0; i < out_node->outputIndex()->size(); i++) { auto out_size = out_node->output_indices_.size();
auto out_tensor_index = size_t(out_node->outputIndex()->GetAs<uint32_t>(i)); for (size_t i = 0; i < out_size; ++i) {
auto out_tensor_index = out_node->output_indices_[i];
bool is_graph_output = false; bool is_graph_output = false;
for (size_t j = 0; j < meta_graph->outputIndex()->size(); j++) { for (size_t j = 0; j < graph_out_size; ++j) {
if (out_tensor_index == size_t(meta_graph->outputIndex()->GetAs<uint32_t>(j))) { if (out_tensor_index == model->output_indices_[j]) {
is_graph_output = true; is_graph_output = true;
break; break;
} }
@ -206,34 +203,39 @@ void LiteSession::InitGraphOutputNodeMap(const lite::Model *model) {
MS_ASSERT(out_tensor_index < this->tensors_.size()); MS_ASSERT(out_tensor_index < this->tensors_.size());
auto *out_tensor = this->tensors_.at(out_tensor_index); auto *out_tensor = this->tensors_.at(out_tensor_index);
MS_ASSERT(out_tensor != nullptr); MS_ASSERT(out_tensor != nullptr);
auto *ms_tensor = new tensor::LiteTensor(out_tensor); auto *ms_tensor = new (std::nothrow) tensor::LiteTensor(out_tensor);
MS_ASSERT(nullptr != ms_tensor); if (ms_tensor == nullptr) {
this->output_node_map_[out_node->name()->str()].emplace_back(ms_tensor); MS_LOG(ERROR) << "new lite tensor fail!";
return;
}
this->output_node_map_[out_node->name_].emplace_back(ms_tensor);
} }
} }
} }
void LiteSession::InitGraphOutputTensorNames(const lite::Model *model) { void LiteSession::InitGraphOutputTensorNames(const lite::Model *model) {
MS_ASSERT(model != nullptr); MS_ASSERT(model != nullptr);
auto meta_graph = model->GetMetaGraph();
MS_ASSERT(this->output_tensor_names_.empty()); MS_ASSERT(this->output_tensor_names_.empty());
MS_ASSERT(meta_graph != nullptr); auto out_size = model->output_indices_.size();
for (auto output_index : *meta_graph->outputIndex()) { for (size_t i = 0; i < out_size; ++i) {
this->output_tensor_names_.emplace_back(std::to_string(output_index)); this->output_tensor_names_.emplace_back(std::to_string(model->output_indices_[i]));
} }
} }
void LiteSession::InitGraphOutputTensorMap(const lite::Model *model) { void LiteSession::InitGraphOutputTensorMap(const lite::Model *model) {
MS_ASSERT(model != nullptr); MS_ASSERT(model != nullptr);
auto meta_graph = model->GetMetaGraph();
MS_ASSERT(this->output_tensor_map_.empty()); MS_ASSERT(this->output_tensor_map_.empty());
MS_ASSERT(meta_graph != nullptr); auto graph_out_size = model->output_indices_.size();
for (auto graph_out_index : *(meta_graph->outputIndex())) { for (size_t i = 0; i < graph_out_size; ++i) {
size_t graph_out_index = model->output_indices_[i];
MS_ASSERT(graph_out_index < this->tensors_.size()); MS_ASSERT(graph_out_index < this->tensors_.size());
auto *out_tensor = this->tensors_.at(graph_out_index); auto *out_tensor = this->tensors_.at(graph_out_index);
MS_ASSERT(out_tensor != nullptr); MS_ASSERT(out_tensor != nullptr);
auto *ms_tensor = new tensor::LiteTensor(out_tensor); auto *ms_tensor = new (std::nothrow) tensor::LiteTensor(out_tensor);
MS_ASSERT(nullptr != ms_tensor); if (ms_tensor == nullptr) {
MS_LOG(ERROR) << "new lite tensor fail!";
return;
}
this->output_tensor_map_.insert(std::make_pair(std::to_string(graph_out_index), ms_tensor)); this->output_tensor_map_.insert(std::make_pair(std::to_string(graph_out_index), ms_tensor));
} }
} }
@ -272,7 +274,7 @@ int LiteSession::CompileGraph(Model *model) {
} }
executor->Prepare(this->kernels_); executor->Prepare(this->kernels_);
model->FreeMetaGraph(); model->Free();
return RET_OK; return RET_OK;
} }

@ -13,34 +13,59 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#include "src/ops/primitive_c.h" #include "src/ops/primitive_c.h"
#include "include/model.h" #include "include/model.h"
#include "utils/log_adapter.h" #include "utils/log_adapter.h"
#include "include/errorcode.h"
#include "src/common/graph_util.h"
namespace mindspore::lite { namespace mindspore::lite {
namespace {
class ModelImpl { bool ConvertNodes(const schema::MetaGraph *meta_graph, Model *model) {
public: for (size_t i = 0; i < meta_graph->nodes()->size(); ++i) {
static ModelImpl *Import(const char *model_buf, size_t size); Model::Node *node = new (std::nothrow) Model::Node();
ModelImpl() = default; if (node == nullptr) {
explicit ModelImpl(const char *model_buf, size_t size) : model_buf_(model_buf), buf_size_(size) { MS_LOG(ERROR) << "new node fail!";
meta_graph_ = schema::GetMetaGraph(model_buf); return false;
}
auto c_node = meta_graph->nodes()->GetAs<schema::CNode>(i);
auto src_prim = c_node->primitive();
node->primitive_ = PrimitiveC::UnPackFromSchemaPrimitive(const_cast<schema::Primitive *>(src_prim));
if (node->primitive_ == nullptr) {
MS_LOG(ERROR) << "unpack primitive == nullptr!";
return false;
}
node->primitive_->SetQuantType(c_node->quantType());
node->name_ = c_node->name()->c_str();
node->node_type_ = c_node->nodeType();
auto count = c_node->inputIndex()->size();
for (uint32_t j = 0; j < count; ++j) {
node->input_indices_.push_back(size_t(c_node->inputIndex()->GetAs<uint32_t>(j)));
}
count = c_node->outputIndex()->size();
for (uint32_t j = 0; j < count; ++j) {
node->output_indices_.push_back(size_t(c_node->outputIndex()->GetAs<uint32_t>(j)));
}
model->nodes_.push_back(node);
} }
virtual ~ModelImpl(); return true;
PrimitiveC *GetOp(const std::string &name) const; }
const schema::MetaGraph *meta_graph() const;
void FreeMetaGraph();
int BuildOps();
protected: bool ConvertTensors(const schema::MetaGraph *meta_graph, Model *model) {
const char *model_buf_; auto tensor_count = meta_graph->allTensors()->size();
size_t buf_size_; for (uint32_t i = 0; i < tensor_count; ++i) {
const schema::MetaGraph *meta_graph_ = nullptr; auto *tensor = meta_graph->allTensors()->GetAs<schema::Tensor>(i);
std::map<std::string, PrimitiveC *> ops_; if (tensor == nullptr) {
}; MS_LOG(ERROR) << i << "th tensor in model is nullptr";
return false;
}
model->all_tensors_.push_back(const_cast<mindspore::schema::Tensor *>(tensor));
}
return true;
}
} // namespace
ModelImpl *ModelImpl::Import(const char *model_buf, size_t size) { Model *Model::Import(const char *model_buf, size_t size) {
if (model_buf == nullptr) { if (model_buf == nullptr) {
MS_LOG(ERROR) << "The model buf is nullptr"; MS_LOG(ERROR) << "The model buf is nullptr";
return nullptr; return nullptr;
@ -50,95 +75,61 @@ ModelImpl *ModelImpl::Import(const char *model_buf, size_t size) {
MS_LOG(ERROR) << "The buffer is invalid and fail to create graph."; MS_LOG(ERROR) << "The buffer is invalid and fail to create graph.";
return nullptr; return nullptr;
} }
auto *inner_model_buf = new (std::nothrow) char[size]; Model *model = new (std::nothrow) Model();
if (inner_model_buf == nullptr) {
MS_LOG(ERROR) << "new model buf fail.";
return nullptr;
}
memcpy(inner_model_buf, model_buf, size);
auto model = new (std::nothrow) ModelImpl(inner_model_buf, size);
if (model == nullptr) { if (model == nullptr) {
MS_LOG(ERROR) << "Create modelImpl failed"; MS_LOG(ERROR) << "new model fail!";
return nullptr; return nullptr;
} }
auto ret = model->BuildOps(); model->buf = reinterpret_cast<char *>(malloc(size));
if (0 != ret) { if (model->buf == nullptr) {
MS_LOG(ERROR) << "BuildOps failed"; MS_LOG(ERROR) << "new inner model buf fail!";
return nullptr; return nullptr;
} }
return model; memcpy(model->buf, model_buf, size);
} auto meta_graph = schema::GetMetaGraph(model->buf);
if (meta_graph == nullptr) {
PrimitiveC *ModelImpl::GetOp(const std::string &name) const { MS_LOG(ERROR) << "meta_graph is nullptr!";
auto iter = ops_.find(name);
if (iter == ops_.end()) {
return nullptr; return nullptr;
} else {
return iter->second;
} }
}
ModelImpl::~ModelImpl() { if (meta_graph->name() != nullptr) {
delete[](this->model_buf_); model->name_ = meta_graph->name()->c_str();
for (auto iter : ops_) {
delete (iter.second);
} }
ops_.clear(); if (meta_graph->version() != nullptr) {
} model->version_ = meta_graph->version()->c_str();
void ModelImpl::FreeMetaGraph() {
delete[](this->model_buf_);
model_buf_ = nullptr;
}
const schema::MetaGraph *ModelImpl::meta_graph() const { return this->meta_graph_; }
int ModelImpl::BuildOps() {
if (this->meta_graph_ == nullptr) {
MS_LOG(ERROR) << "mete_graph is nullptr";
return -1;
} }
MS_ASSERT(nullptr != meta_graph_->nodes()); auto in_count = meta_graph->inputIndex()->size();
for (size_t i = 0; i < meta_graph_->nodes()->size(); i++) { for (uint32_t i = 0; i < in_count; ++i) {
auto cNode = meta_graph_->nodes()->GetAs<schema::CNode>(i); model->input_indices_.push_back(size_t(meta_graph->inputIndex()->GetAs<uint32_t>(i)));
auto name = cNode->name()->str();
auto srcPrim = cNode->primitive();
auto prim = PrimitiveC::UnPackFromSchemaPrimitive(const_cast<schema::Primitive *>(srcPrim));
prim->SetQuantType(cNode->quantType());
this->ops_[name] = prim;
} }
return 0;
}
Model *Model::Import(const char *model_buf, size_t size) { auto out_count = meta_graph->outputIndex()->size();
auto model = new Model(); for (uint32_t i = 0; i < out_count; ++i) {
model->model_impl_ = ModelImpl::Import(model_buf, size); model->output_indices_.push_back(size_t(meta_graph->outputIndex()->GetAs<uint32_t>(i)));
if (model_buf == nullptr) { }
MS_LOG(ERROR) << "model buf is null"; if (!ConvertNodes(meta_graph, model)) {
delete model;
return nullptr; return nullptr;
} }
if (model->model_impl_ == nullptr) {
MS_LOG(ERROR) << "model impl is null"; if (!ConvertTensors(meta_graph, model)) {
delete model;
return nullptr; return nullptr;
} }
return model; return model;
} }
Model::~Model() { delete (this->model_impl_); } void Model::Free() {
if (this->buf != nullptr) {
mindspore::lite::PrimitiveC *Model::GetOp(const std::string &name) const { free(this->buf);
MS_ASSERT(nullptr != model_impl_); this->buf = nullptr;
return const_cast<PrimitiveC *>(model_impl_->GetOp(name)); }
} auto nodes_size = this->nodes_.size();
for (size_t i = 0; i < nodes_size; ++i) {
void Model::FreeMetaGraph() { auto node = this->nodes_[i];
MS_ASSERT(nullptr != model_impl_); MS_ASSERT(node != nullptr);
model_impl_->FreeMetaGraph(); delete node;
} }
this->nodes_.clear();
const schema::MetaGraph *Model::GetMetaGraph() const {
MS_ASSERT(nullptr != model_impl_);
return model_impl_->meta_graph();
} }
} // namespace mindspore::lite } // namespace mindspore::lite

@ -79,43 +79,42 @@ int Scheduler::ReSizeKernels(const std::vector<kernel::LiteKernel *> &kernels) {
} }
int Scheduler::InferShape(const lite::Model *model, std::vector<tensor::Tensor *> *tensors) { int Scheduler::InferShape(const lite::Model *model, std::vector<tensor::Tensor *> *tensors) {
MS_ASSERT(nullptr != model); MS_ASSERT(model != nullptr);
MS_ASSERT(nullptr != tensors); MS_ASSERT(tensors != nullptr);
auto meta_graph = model->GetMetaGraph();
MS_ASSERT(nullptr != meta_graph);
bool infer_shape_interrupt = false; bool infer_shape_interrupt = false;
uint32_t kernelCount = meta_graph->nodes()->size(); uint32_t kernelCount = model->nodes_.size();
for (uint32_t i = 0; i < kernelCount; i++) { for (uint32_t i = 0; i < kernelCount; ++i) {
auto cNode = meta_graph->nodes()->GetAs<schema::CNode>(i); auto node = model->nodes_[i];
MS_ASSERT(node != nullptr);
std::vector<tensor::Tensor *> inputs; std::vector<tensor::Tensor *> inputs;
std::vector<tensor::Tensor *> outputs; std::vector<tensor::Tensor *> outputs;
auto inIndexes = cNode->inputIndex(); auto in_size = node->input_indices_.size();
for (size_t j = 0; j < inIndexes->size(); j++) { for (size_t j = 0; j < in_size; ++j) {
inputs.emplace_back(tensors->at(size_t(inIndexes->GetAs<uint32_t>(j)))); inputs.emplace_back(tensors->at(node->input_indices_[j]));
} }
auto outIndexes = cNode->outputIndex();
if (outIndexes != nullptr) { auto out_size = node->output_indices_.size();
for (size_t j = 0; j < outIndexes->size(); j++) { for (size_t j = 0; j < out_size; ++j) {
outputs.emplace_back(tensors->at(size_t(outIndexes->GetAs<uint32_t>(j)))); outputs.emplace_back(tensors->at(node->output_indices_[j]));
}
} }
auto *primitive = model->GetOp(cNode->name()->str()); auto *primitive = node->primitive_;
if (primitive == nullptr) { if (primitive == nullptr) {
MS_LOG(ERROR) << "Op " << cNode->name()->str() << " should exist in model, type: " MS_LOG(ERROR) << "Op " << node->name_ << " should exist in model!";
<< schema::EnumNamePrimitiveType(cNode->primitive()->value_type());
return RET_ERROR; return RET_ERROR;
} }
primitive->SetInferFlag(!infer_shape_interrupt); primitive->SetInferFlag(!infer_shape_interrupt);
auto ret = primitive->InferShape(inputs, outputs); auto ret = primitive->InferShape(inputs, outputs);
if (ret == RET_INFER_INVALID) { if (ret == RET_INFER_INVALID) {
MS_LOG(INFO) << "InferShape shouldn't be done before runtime, name: " << cNode->name()->str() MS_LOG(INFO) << "InferShape shouldn't be done before runtime, name: " << node->name_
<< ", type: " << schema::EnumNamePrimitiveType(cNode->primitive()->value_type()) << ", type: "
<< schema::EnumNamePrimitiveType(static_cast<schema::PrimitiveType>(primitive->Type()))
<< "flag set to false."; << "flag set to false.";
primitive->SetInferFlag(false); primitive->SetInferFlag(false);
infer_shape_interrupt = true; infer_shape_interrupt = true;
} else if (ret != RET_OK) { } else if (ret != RET_OK) {
MS_LOG(ERROR) << "InferShape failed, name: " << cNode->name()->str() MS_LOG(ERROR) << "InferShape failed, name: " << node->name_
<< ", type: " << schema::EnumNamePrimitiveType(cNode->primitive()->value_type()); << ", type: "
<< schema::EnumNamePrimitiveType(static_cast<schema::PrimitiveType>(primitive->Type()));
return RET_INFER_ERR; return RET_INFER_ERR;
} }
} }
@ -125,33 +124,34 @@ int Scheduler::InferShape(const lite::Model *model, std::vector<tensor::Tensor *
int Scheduler::InitOp2Kernel(const lite::Model *model, std::vector<tensor::Tensor *> *tensors, int Scheduler::InitOp2Kernel(const lite::Model *model, std::vector<tensor::Tensor *> *tensors,
std::vector<kernel::LiteKernel *> *kernels) { std::vector<kernel::LiteKernel *> *kernels) {
MS_ASSERT(nullptr != model); MS_ASSERT(model != nullptr);
MS_ASSERT(nullptr != tensors); MS_ASSERT(tensors != nullptr);
auto meta_graph = model->GetMetaGraph(); uint32_t kernelCount = model->nodes_.size();
MS_ASSERT(nullptr != meta_graph); auto graph_output_node_indexes = GetGraphOutputNodes(model);
uint32_t kernelCount = meta_graph->nodes()->size(); for (uint32_t i = 0; i < kernelCount; ++i) {
auto graph_output_node_indexes = GetGraphOutputNodes(meta_graph); auto node = model->nodes_[i];
for (uint32_t i = 0; i < kernelCount; i++) { MS_ASSERT(node != nullptr);
auto cNode = meta_graph->nodes()->GetAs<schema::CNode>(i);
std::vector<tensor::Tensor *> inputs; std::vector<tensor::Tensor *> inputs;
std::vector<tensor::Tensor *> outputs; std::vector<tensor::Tensor *> outputs;
auto inIndexes = cNode->inputIndex(); auto in_size = node->input_indices_.size();
for (size_t j = 0; j < inIndexes->size(); j++) { for (size_t j = 0; j < in_size; ++j) {
inputs.emplace_back(tensors->at(size_t(inIndexes->GetAs<uint32_t>(j)))); inputs.emplace_back(tensors->at(node->input_indices_[j]));
} }
auto outIndexes = cNode->outputIndex(); auto out_size = node->output_indices_.size();
for (size_t j = 0; j < outIndexes->size(); j++) { for (size_t j = 0; j < out_size; ++j) {
outputs.emplace_back(tensors->at(size_t(outIndexes->GetAs<uint32_t>(j)))); outputs.emplace_back(tensors->at(node->output_indices_[j]));
} }
auto *primitive = model->GetOp(cNode->name()->str()); auto *primitive = node->primitive_;
auto *kernel = this->ScheduleNode(inputs, outputs, primitive, cNode); MS_ASSERT(primitive != nullptr);
if (nullptr == kernel) { auto *kernel = this->ScheduleNode(inputs, outputs, primitive, node);
MS_LOG(ERROR) << "ScheduleNode return nullptr, name: " << cNode->name()->str() if (kernel == nullptr) {
<< ", type: " << schema::EnumNamePrimitiveType(cNode->primitive()->value_type()); MS_LOG(ERROR) << "ScheduleNode return nullptr, name: " << node->name_
<< ", type: "
<< schema::EnumNamePrimitiveType(static_cast<schema::PrimitiveType>(primitive->Type()));
return RET_ERROR; return RET_ERROR;
} }
SetKernelTensorDataType(kernel); SetKernelTensorDataType(kernel);
kernel->set_name(cNode->name()->str()); kernel->set_name(node->name_);
kernel->set_is_model_output(IsContain(graph_output_node_indexes, size_t(i))); kernel->set_is_model_output(IsContain(graph_output_node_indexes, size_t(i)));
kernels->emplace_back(kernel); kernels->emplace_back(kernel);
} }
@ -231,20 +231,20 @@ kernel::LiteKernel *Scheduler::CreateSubKernel(const std::vector<kernel::LiteKer
kernel::LiteKernel *Scheduler::ScheduleNode(const std::vector<tensor::Tensor *> &in_tensors, kernel::LiteKernel *Scheduler::ScheduleNode(const std::vector<tensor::Tensor *> &in_tensors,
const std::vector<tensor::Tensor *> &out_tensors, const std::vector<tensor::Tensor *> &out_tensors,
const mindspore::lite::PrimitiveC *primitive, const schema::CNode *cnode) { const mindspore::lite::PrimitiveC *primitive, const Model::Node *node) {
MS_ASSERT(nullptr != primitive); MS_ASSERT(primitive != nullptr);
TypeId data_type = GetFirstFp32Fp16OrInt8Type(in_tensors); TypeId data_type = GetFirstFp32Fp16OrInt8Type(in_tensors);
kernel::KernelKey desc{kernel::KERNEL_ARCH::kCPU, data_type, static_cast<schema::PrimitiveType>(primitive->Type())}; kernel::KernelKey desc{kernel::KERNEL_ARCH::kCPU, data_type, static_cast<schema::PrimitiveType>(primitive->Type())};
if (context_->device_ctx_.type == DT_GPU) { if (context_->device_ctx_.type == DT_GPU) {
desc.arch = kernel::KERNEL_ARCH::kGPU; desc.arch = kernel::KERNEL_ARCH::kGPU;
auto *kernel = KernelRegistry::GetInstance()->GetKernel(in_tensors, out_tensors, primitive, context_, desc); auto *kernel = KernelRegistry::GetInstance()->GetKernel(in_tensors, out_tensors, primitive, context_, desc);
if (nullptr != kernel) { if (kernel != nullptr) {
kernel->set_desc(desc); kernel->set_desc(desc);
return kernel; return kernel;
} else { } else {
MS_LOG(ERROR) << "Not supported GPU Op " MS_LOG(ERROR) << "Not supported GPU Op "
<< schema::EnumNamePrimitiveType(static_cast<schema::PrimitiveType>(primitive->Type())) << " " << schema::EnumNamePrimitiveType(static_cast<schema::PrimitiveType>(primitive->Type())) << " "
<< (cnode->name()->str()); << node->name_;
} }
} }

@ -36,7 +36,7 @@ class Scheduler {
kernel::LiteKernel *ScheduleNode(const std::vector<tensor::Tensor *> &in_tensors, kernel::LiteKernel *ScheduleNode(const std::vector<tensor::Tensor *> &in_tensors,
const std::vector<tensor::Tensor *> &out_tensors, const std::vector<tensor::Tensor *> &out_tensors,
const mindspore::lite::PrimitiveC *primitive, const mindspore::lite::PrimitiveC *primitive,
const schema::CNode *cnode); const Model::Node *cnode);
private: private:
int InitOp2Kernel(const lite::Model *model, std::vector<tensor::Tensor *> *tensors, int InitOp2Kernel(const lite::Model *model, std::vector<tensor::Tensor *> *tensors,

@ -494,10 +494,11 @@ while read line; do
continue continue
fi fi
echo ${model_name} >> "${run_benchmark_log_file}" echo ${model_name} >> "${run_benchmark_log_file}"
echo 'convert mode name: '${model_name}' begin.'
echo './converter_lite --fmk=TFLITE --modelFile='${models_path}'/'${model_name}' --outputFile='${ms_models_path}'/'${model_name}_posttraining' --quantType=PostTraining --config_file='${models_path}'/'${model_name}'_posttraining.config' >> "${run_benchmark_log_file}" echo './converter_lite --fmk=TFLITE --modelFile='${models_path}'/'${model_name}' --outputFile='${ms_models_path}'/'${model_name}_posttraining' --quantType=PostTraining --config_file='${models_path}'/'${model_name}'_posttraining.config' >> "${run_benchmark_log_file}"
./converter_lite --fmk=TFLITE --modelFile=$models_path/${model_name} --outputFile=${ms_models_path}/${model_name}_posttraining --quantType=PostTraining --config_file=${models_path}/${model_name}_posttraining.config || Convert_status=$? ./converter_lite --fmk=TFLITE --modelFile=$models_path/${model_name} --outputFile=${ms_models_path}/${model_name}_posttraining --quantType=PostTraining --config_file=${models_path}/${model_name}_posttraining.config || Convert_status=$?
done < ${models_tflite_posttraining_config} done < ${models_tflite_posttraining_config}
# Convert TFLite AwareTraining models: # Convert TFLite AwareTraining models:
while read line; do while read line; do
model_name=${line} model_name=${line}

@ -353,7 +353,7 @@ int Benchmark::RunBenchmark(const std::string &deviceType) {
return RET_ERROR; return RET_ERROR;
} }
auto model = lite::Model::Import(graphBuf, size); auto model = lite::Model::Import(graphBuf, size);
auto model_version = model->GetMetaGraph()->version()->str(); auto model_version = model->version_;
if (model_version != Version()) { if (model_version != Version()) {
MS_LOG(WARNING) << "model version is "<< model_version << ", inference version is " << Version() << " not equal"; MS_LOG(WARNING) << "model version is "<< model_version << ", inference version is " << Version() << " not equal";
} }

@ -324,7 +324,6 @@ int TimeProfile::RunTimeProfile() {
MS_LOG(ERROR) << "Import model file failed while running " << modelName.c_str(); MS_LOG(ERROR) << "Import model file failed while running " << modelName.c_str();
std::cerr << "Import model file failed while running " << modelName.c_str() << std::endl; std::cerr << "Import model file failed while running " << modelName.c_str() << std::endl;
delete session_; delete session_;
delete model;
return RET_ERROR; return RET_ERROR;
} }
auto ret = session_->CompileGraph(model); auto ret = session_->CompileGraph(model);

Loading…
Cancel
Save