forked from mindspore-Ecosystem/mindspore
constant fold approve multi output
This commit is contained in:
parent
f42b3bbfbc
commit
e121bcd3be
|
@ -236,6 +236,136 @@ MetaGraphTptr BuildMixGraph() {
|
|||
// final output
|
||||
return meta_graph;
|
||||
}
|
||||
MetaGraphTptr BuildSplitGraph() {
|
||||
auto meta_graph = std::make_shared<schema::MetaGraphT>();
|
||||
meta_graph->name = "graph";
|
||||
// slice node
|
||||
auto split_node = std::make_unique<schema::CNodeT>();
|
||||
split_node->inputIndex = {0};
|
||||
split_node->outputIndex = {1, 2};
|
||||
split_node->primitive = std::make_unique<schema::PrimitiveT>();
|
||||
split_node->primitive->value.type = schema::PrimitiveType_Split;
|
||||
std::unique_ptr<schema::SplitT> attr = std::make_unique<schema::SplitT>();
|
||||
attr->numberSplit = 2;
|
||||
attr->splitDim = 1;
|
||||
split_node->primitive->value.value = attr.release();
|
||||
split_node->name = "split";
|
||||
meta_graph->nodes.emplace_back(std::move(split_node));
|
||||
|
||||
meta_graph->inputIndex = {0, 3, 4};
|
||||
meta_graph->outputIndex = {5, 6};
|
||||
|
||||
auto mul_node1 = std::make_unique<schema::CNodeT>();
|
||||
mul_node1->inputIndex = {1, 3};
|
||||
mul_node1->outputIndex = {5};
|
||||
mul_node1->primitive = std::make_unique<schema::PrimitiveT>();
|
||||
mul_node1->primitive->value.type = schema::PrimitiveType_Mul;
|
||||
std::unique_ptr<schema::MulT> mul_attr = std::make_unique<schema::MulT>();
|
||||
mul_node1->primitive->value.value = mul_attr.release();
|
||||
mul_node1->name = "mul1";
|
||||
meta_graph->nodes.emplace_back(std::move(mul_node1));
|
||||
|
||||
auto mul_node2 = std::make_unique<schema::CNodeT>();
|
||||
mul_node2->inputIndex = {2, 4};
|
||||
mul_node2->outputIndex = {6};
|
||||
mul_node2->primitive = std::make_unique<schema::PrimitiveT>();
|
||||
mul_node2->primitive->value.type = schema::PrimitiveType_Mul;
|
||||
std::unique_ptr<schema::MulT> mul2_attr = std::make_unique<schema::MulT>();
|
||||
mul_node2->primitive->value.value = mul2_attr.release();
|
||||
mul_node2->name = "mul2";
|
||||
meta_graph->nodes.emplace_back(std::move(mul_node2));
|
||||
|
||||
// input 0: data1
|
||||
auto input0 = std::make_unique<schema::TensorT>();
|
||||
input0->nodeType = schema::NodeType::NodeType_ValueNode;
|
||||
input0->format = schema::Format_NHWC;
|
||||
input0->dataType = TypeId::kNumberTypeFloat32;
|
||||
input0->dims = {1, 2, 2, 3};
|
||||
input0->offset = -1;
|
||||
auto input0_data = new(std::nothrow) float[2 * 2 * 3];
|
||||
for (auto i = 0; i < 2 * 2 * 3; i++) {
|
||||
input0_data[i] = i;
|
||||
}
|
||||
input0->data.resize(sizeof(float) * 2 * 2 * 3);
|
||||
memcpy(input0->data.data(), input0_data, 2 * 2 * 3 * sizeof(float));
|
||||
delete[] input0_data;
|
||||
meta_graph->allTensors.emplace_back(std::move(input0));
|
||||
|
||||
// split output1
|
||||
auto split_output1 = std::make_unique<schema::TensorT>();
|
||||
split_output1->nodeType = schema::NodeType::NodeType_Parameter;
|
||||
split_output1->format = schema::Format_NHWC;
|
||||
split_output1->dataType = TypeId::kNumberTypeFloat32;
|
||||
split_output1->dims = {1, 1, 2, 3};
|
||||
split_output1->offset = -1;
|
||||
split_output1->data.resize(sizeof(float) * 1 * 2 * 3);
|
||||
auto split_output_data1 = new(std::nothrow) float[1 * 2 * 3];
|
||||
memcpy(split_output1->data.data(), split_output_data1, 1 * 2 * 3 * sizeof(float));
|
||||
delete[] split_output_data1;
|
||||
meta_graph->allTensors.emplace_back(std::move(split_output1));
|
||||
|
||||
// split output2
|
||||
auto split_output2 = std::make_unique<schema::TensorT>();
|
||||
split_output2->nodeType = schema::NodeType::NodeType_Parameter;
|
||||
split_output2->format = schema::Format_NHWC;
|
||||
split_output2->dataType = TypeId::kNumberTypeFloat32;
|
||||
split_output2->dims = {1, 1, 2, 3};
|
||||
split_output2->offset = -1;
|
||||
split_output2->data.resize(sizeof(float) * 1 * 2 * 3);
|
||||
auto split_output_data2 = new(std::nothrow) float[1 * 2 * 3];
|
||||
memcpy(split_output2->data.data(), split_output_data2, 1 * 2 * 3 * sizeof(float));
|
||||
delete[] split_output_data2;
|
||||
meta_graph->allTensors.emplace_back(std::move(split_output2));
|
||||
|
||||
// input 1: data2
|
||||
auto input1 = std::make_unique<schema::TensorT>();
|
||||
input1->nodeType = schema::NodeType::NodeType_ValueNode;
|
||||
input1->format = schema::Format_NHWC;
|
||||
input1->dataType = TypeId::kNumberTypeFloat32;
|
||||
input1->dims = {1, 1, 2, 3};
|
||||
input1->offset = -1;
|
||||
input1->data.resize(sizeof(float) * 2 * 3);
|
||||
auto input1_data = new(std::nothrow) float[2 * 3];
|
||||
for (auto i = 0; i < 2 * 3; i++) {
|
||||
input1_data[i] = i;
|
||||
}
|
||||
memcpy(input1->data.data(), input1_data, 2 * 3 * sizeof(float));
|
||||
delete[] input1_data;
|
||||
meta_graph->allTensors.emplace_back(std::move(input1));
|
||||
|
||||
// input 2: data3
|
||||
auto input2 = std::make_unique<schema::TensorT>();
|
||||
input2->nodeType = schema::NodeType::NodeType_ValueNode;
|
||||
input2->format = schema::Format_NHWC;
|
||||
input2->dataType = TypeId::kNumberTypeFloat32;
|
||||
input2->dims = {1, 1, 2, 3};
|
||||
input2->offset = -1;
|
||||
input2->data.resize(sizeof(float) * 2 * 3);
|
||||
auto input2_data = new(std::nothrow) float[2 * 3];
|
||||
for (auto i = 0; i < 2 * 3; i++) {
|
||||
input2_data[i] = 10;
|
||||
}
|
||||
memcpy(input2->data.data(), input2_data, 2 * 3 * sizeof(float));
|
||||
delete[] input2_data;
|
||||
meta_graph->allTensors.emplace_back(std::move(input2));
|
||||
|
||||
// final mul output1
|
||||
auto mul_output = std::make_unique<schema::TensorT>();
|
||||
mul_output->nodeType = schema::NodeType::NodeType_Parameter;
|
||||
mul_output->format = schema::Format_NHWC;
|
||||
mul_output->dataType = TypeId::kNumberTypeFloat32;
|
||||
mul_output->dims = {1, 1, 2, 3};
|
||||
meta_graph->allTensors.emplace_back(std::move(mul_output));
|
||||
|
||||
// final mul output2
|
||||
auto mul_output2 = std::make_unique<schema::TensorT>();
|
||||
mul_output2->nodeType = schema::NodeType::NodeType_Parameter;
|
||||
mul_output2->format = schema::Format_NHWC;
|
||||
mul_output2->dataType = TypeId::kNumberTypeFloat32;
|
||||
mul_output2->dims = {1, 1, 2, 3};
|
||||
meta_graph->allTensors.emplace_back(std::move(mul_output2));
|
||||
return meta_graph;
|
||||
}
|
||||
} // namespace
|
||||
TEST_F(ConstantFoldingFusionTest, TestADDConstantFold) {
|
||||
auto meta_graph = BuildGraph(schema::PrimitiveType_Add, new schema::AddT);
|
||||
|
@ -483,4 +613,19 @@ TEST_F(ConstantFoldingFusionTest, TestCastDimsConstantFold) {
|
|||
auto new_meta_graph = lite::Export(new_graph);
|
||||
ASSERT_EQ(new_meta_graph->nodes.size(), 0);
|
||||
}
|
||||
|
||||
TEST_F(ConstantFoldingFusionTest, TestSplitConstantFold) {
|
||||
auto meta_graph = BuildSplitGraph();
|
||||
auto input_tensor = meta_graph->allTensors.at(0).get();
|
||||
input_tensor->dataType = kNumberTypeFloat32;
|
||||
auto func_graph = lite::ModelParser::Fb2Anf(meta_graph.get());
|
||||
auto optimizer = std::make_shared<opt::GraphOptimizer>();
|
||||
auto pm = std::make_shared<opt::PassManager>("test", false);
|
||||
pm->AddPass(std::make_shared<opt::ConstFoldPass>());
|
||||
optimizer->AddPassManager(pm);
|
||||
FuncGraphPtr new_graph = optimizer->Optimize(func_graph);
|
||||
ASSERT_NE(nullptr, new_graph);
|
||||
auto new_meta_graph = lite::Export(new_graph);
|
||||
ASSERT_EQ(new_meta_graph->nodes.size(), 0);
|
||||
}
|
||||
} // namespace mindspore
|
||||
|
|
|
@ -319,7 +319,7 @@ schema::PrimitiveType GetCNodeType(const BaseRef &n) {
|
|||
if (utils::isa<PrimitiveCPtr>(value)) {
|
||||
auto primitive = value->cast<PrimitiveCPtr>();
|
||||
MS_ASSERT(primitive != nullptr);
|
||||
return (schema::PrimitiveType)primitive->Type();
|
||||
return (schema::PrimitiveType) primitive->Type();
|
||||
} else if (utils::isa<Primitive>(value)) {
|
||||
auto primitive = value->cast<PrimitivePtr>();
|
||||
MS_ASSERT(primitive != nullptr);
|
||||
|
@ -392,8 +392,8 @@ size_t GetOutputTensorNum(const AnfNodePtr &node) {
|
|||
bool IsMultiOutputTensors(const FuncGraphPtr &graph, const AnfNodePtr &node) {
|
||||
auto output_node_list = GetRealNodeUsedList(graph, node);
|
||||
if (output_node_list->size() != 1) {
|
||||
MS_LOG(DEBUG) << "fusion node has multi output nodes";
|
||||
return true;
|
||||
MS_LOG(DEBUG) << "fusion node has multi output nodes";
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -412,5 +412,50 @@ std::shared_ptr<std::vector<std::pair<AnfNodePtr, int>>> GetRealNodeUsedList(con
|
|||
std::copy(output_info_list.begin(), output_info_list.end(), std::back_inserter(*output_node_list));
|
||||
return output_node_list;
|
||||
}
|
||||
size_t GetTupleGetItemOutIndex(const CNodePtr &tuple_get_item) {
|
||||
MS_ASSERT(tuple_get_item != nullptr);
|
||||
if (tuple_get_item->size() != kTupleGetItemInputSize) {
|
||||
MS_LOG(ERROR) << "The node tuple_get_item must have 2 inputs!";
|
||||
return -1;
|
||||
}
|
||||
auto output_index_value_node = tuple_get_item->input(kInputNodeOutputIndexInTupleGetItem);
|
||||
MS_ASSERT(output_index_value_node != nullptr);
|
||||
auto value_node = output_index_value_node->cast<ValueNodePtr>();
|
||||
MS_ASSERT(value_node != nullptr);
|
||||
return IntToSize(GetValue<int>(value_node->value()));
|
||||
}
|
||||
std::shared_ptr<std::vector<std::pair<AnfNodePtr, int>>> GetRealNodeUsedListByOutputIdx(const FuncGraphPtr &graph,
|
||||
const AnfNodePtr &node,
|
||||
size_t output_index) {
|
||||
MS_ASSERT(graph != nullptr);
|
||||
MS_ASSERT(node != nullptr);
|
||||
auto output_node_list = std::make_shared<std::vector<std::pair<AnfNodePtr, int>>>();
|
||||
auto manager = graph->manager();
|
||||
MS_ASSERT(manager != nullptr);
|
||||
auto iter = manager->node_users().find(node);
|
||||
if (iter == manager->node_users().end()) {
|
||||
MS_LOG(ERROR) << "node has no output in manager";
|
||||
return output_node_list;
|
||||
}
|
||||
auto output_info_list = iter->second;
|
||||
for (const auto &output_info : output_info_list) {
|
||||
size_t used_output_index;
|
||||
if (GetCNodeType(output_info.first) == schema::PrimitiveType_TupleGetItem) {
|
||||
used_output_index = GetTupleGetItemOutIndex(utils::cast<CNodePtr>(output_info.first));
|
||||
} else if (GetCNodeType(node) == schema::PrimitiveType_TupleGetItem) {
|
||||
used_output_index = output_index;
|
||||
} else {
|
||||
if (output_index != 0) {
|
||||
MS_LOG(ERROR) << "node has no output in manager";
|
||||
return output_node_list;
|
||||
}
|
||||
return output_node_list;
|
||||
}
|
||||
if (used_output_index == output_index) {
|
||||
output_node_list->push_back(output_info);
|
||||
}
|
||||
}
|
||||
return output_node_list;
|
||||
}
|
||||
} // namespace opt
|
||||
} // namespace mindspore
|
||||
|
|
|
@ -63,6 +63,8 @@ bool CheckIsAllInputsParam(const AnfNodePtr &node);
|
|||
size_t GetOutputTensorNum(const AnfNodePtr &node);
|
||||
|
||||
bool IsMultiOutputTensors(const FuncGraphPtr &graph, const AnfNodePtr &node);
|
||||
|
||||
size_t GetTupleGetItemOutIndex(const CNodePtr &tuple_get_item);
|
||||
} // namespace opt
|
||||
} // namespace mindspore
|
||||
#endif // MINDSPORE_LITE_SRC_PASS_COMMON_GLLO_UTILS_H_
|
||||
|
|
|
@ -41,7 +41,7 @@ std::vector<Tensor *> GetCNodeInputTensors(const CNodePtr &CNode) {
|
|||
auto tensorT = tmp_meta_graph->allTensors.at(input_index).get();
|
||||
auto tensor_shape = tensorT->dims;
|
||||
auto lite_tensor =
|
||||
new (std::nothrow) Tensor(TypeId(tensorT->dataType), tensor_shape, tensorT->format, tensorT->nodeType);
|
||||
new (std::nothrow) Tensor(TypeId(tensorT->dataType), tensor_shape, tensorT->format, tensorT->nodeType);
|
||||
if (lite_tensor == nullptr) {
|
||||
MS_LOG(ERROR) << "lite tensor is nullptr";
|
||||
return input_tensors;
|
||||
|
@ -106,7 +106,7 @@ kernel::LiteKernel *GetLiteKernel(std::vector<Tensor *> inputs, std::vector<Tens
|
|||
mindspore::lite::PrimitiveC *primitive) {
|
||||
MS_ASSERT(nullptr != lite_primitive);
|
||||
auto data_type = inputs.front()->data_type();
|
||||
kernel::KernelKey desc{kernel::KERNEL_ARCH::kCPU, data_type, (schema::PrimitiveType)primitive->Type()};
|
||||
kernel::KernelKey desc{kernel::KERNEL_ARCH::kCPU, data_type, (schema::PrimitiveType) primitive->Type()};
|
||||
lite::Context context;
|
||||
auto creator = lite::KernelRegistry::GetInstance()->GetCreator(desc);
|
||||
if (creator != nullptr) {
|
||||
|
@ -115,6 +115,44 @@ kernel::LiteKernel *GetLiteKernel(std::vector<Tensor *> inputs, std::vector<Tens
|
|||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
lite::STATUS ReplaceCNode(const FuncGraphPtr &func_graph, const CNodePtr &any_node, const AnfNodePtr &input_node,
|
||||
std::vector<Tensor *> output_tensors, size_t replace_index) {
|
||||
MS_ASSERT(func_graph != nullptr);
|
||||
auto manager = func_graph->manager();
|
||||
MS_ASSERT(manager != nullptr);
|
||||
if (output_tensors.size() != 1) {
|
||||
for (size_t k = 0; k < output_tensors.size(); k++) {
|
||||
auto used_node_list = GetRealNodeUsedListByOutputIdx(func_graph, input_node, k);
|
||||
if (used_node_list->size() != 1) {
|
||||
MS_LOG(ERROR) << " output must tuple_getitem";
|
||||
return lite::RET_ERROR;
|
||||
}
|
||||
auto tuple_node = used_node_list->at(0).first;
|
||||
if (GetCNodeType(tuple_node) == schema::PrimitiveType_TupleGetItem) {
|
||||
auto new_parameter = CreateNewParamter(func_graph, output_tensors.at(k));
|
||||
if (new_parameter == nullptr) {
|
||||
MS_LOG(ERROR) << "CreateNewParamter failed, name: " << input_node->fullname_with_scope();
|
||||
return lite::RET_ERROR;
|
||||
}
|
||||
new_parameter->set_name(input_node->fullname_with_scope() + "_const_" + std::to_string(k));
|
||||
manager->Replace(tuple_node, new_parameter);
|
||||
} else {
|
||||
MS_LOG(ERROR) << " multi out tensor must connect tuple-getitem: " << input_node->fullname_with_scope();
|
||||
return lite::RET_ERROR;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto new_parameter = CreateNewParamter(func_graph, output_tensors.front());
|
||||
if (new_parameter == nullptr) {
|
||||
MS_LOG(ERROR) << "CreateNewParamter failed, name: " << input_node->fullname_with_scope();
|
||||
return lite::RET_ERROR;
|
||||
}
|
||||
new_parameter->set_name(input_node->fullname_with_scope());
|
||||
any_node->set_input(replace_index, new_parameter);
|
||||
}
|
||||
return lite::RET_OK;
|
||||
}
|
||||
} // namespace
|
||||
void FreeTensors(std::vector<Tensor *> *input_tensor, std::vector<Tensor *> *output_tensor) {
|
||||
if (input_tensor != nullptr) {
|
||||
|
@ -140,64 +178,66 @@ const AnfNodePtr ConstFoldPass::Process(const FuncGraphPtr &func_graph, const An
|
|||
}
|
||||
auto any_node = node->cast<CNodePtr>();
|
||||
CheckIfCNodeIsNull(any_node);
|
||||
bool changed = false;
|
||||
for (size_t i = 1; i < any_node->inputs().size(); i++) {
|
||||
auto input_node = any_node->input(i);
|
||||
if (input_node->isa<CNode>() && CheckIsAllInputsParam(input_node)) {
|
||||
auto input_cnode = input_node->cast<CNodePtr>();
|
||||
auto input_tensors = GetCNodeInputTensors(input_cnode);
|
||||
if (input_tensors.empty() || input_tensors.size() != input_cnode->inputs().size() - 1) {
|
||||
FreeTensors(&input_tensors, nullptr);
|
||||
continue;
|
||||
if (!input_node->isa<CNode>() || !CheckIsAllInputsParam(input_node)) {
|
||||
continue;
|
||||
}
|
||||
auto input_cnode = input_node->cast<CNodePtr>();
|
||||
auto input_tensors = GetCNodeInputTensors(input_cnode);
|
||||
if (input_tensors.empty() || input_tensors.size() != input_cnode->inputs().size() - 1) {
|
||||
FreeTensors(&input_tensors, nullptr);
|
||||
continue;
|
||||
}
|
||||
changed = true;
|
||||
MS_LOG(INFO) << "Begin fold node:" << input_node->fullname_with_scope();
|
||||
auto output_nums = GetOutputTensorNum(input_cnode);
|
||||
std::vector<Tensor *> output_tensors{output_nums, new Tensor()};
|
||||
auto lite_primitive = GetValueNode<std::shared_ptr<PrimitiveC>>(input_cnode->input(0));
|
||||
if (lite_primitive == nullptr) {
|
||||
MS_LOG(ERROR) << "lite_primitive is nullptr";
|
||||
FreeTensors(&input_tensors, &output_tensors);
|
||||
return nullptr;
|
||||
}
|
||||
// here, input_tensor's format need to be transposed nhwc according to fmkType,
|
||||
// but for the time being, we only transpose the tensor with 0/1/2/3D.
|
||||
// Others should be added in future.
|
||||
for (size_t j = 0; j < input_tensors.size(); ++j) {
|
||||
input_tensors[j]->SetFormat(schema::Format_NHWC);
|
||||
if (input_tensors[j]->shape().size() == 4) {
|
||||
MS_LOG(INFO) << "init input_tensor format to nhwc";
|
||||
}
|
||||
MS_LOG(INFO) << "Begin fold node:" << input_node->fullname_with_scope();
|
||||
auto output_nums = GetOutputTensorNum(input_cnode);
|
||||
std::vector<Tensor *> output_tensors{output_nums, new Tensor()};
|
||||
auto lite_primitive = GetValueNode<std::shared_ptr<PrimitiveC>>(input_cnode->input(0));
|
||||
if (lite_primitive == nullptr) {
|
||||
MS_LOG(ERROR) << "lite_primitive is nullptr";
|
||||
FreeTensors(&input_tensors, &output_tensors);
|
||||
return nullptr;
|
||||
}
|
||||
// here, input_tensor's format need to be transposed nhwc according to fmkType,
|
||||
// but for the time being, we only transpose the tensor with 0/1/2/3D.
|
||||
// Others should be added in future.
|
||||
for (size_t j = 0; j < input_tensors.size(); ++j) {
|
||||
input_tensors[j]->SetFormat(schema::Format_NHWC);
|
||||
if (input_tensors[j]->shape().size() == 4) {
|
||||
MS_LOG(INFO) << "init input_tensor format to nhwc";
|
||||
}
|
||||
}
|
||||
lite_primitive->InferShape(input_tensors, output_tensors);
|
||||
auto parameter = kernel::PopulateParameter(lite_primitive.get());
|
||||
if (parameter == nullptr) {
|
||||
MS_LOG(ERROR) << "PopulateParameter return nullptr, type: "
|
||||
<< schema::EnumNamePrimitiveType((schema::PrimitiveType)(lite_primitive->Type()));
|
||||
return nullptr;
|
||||
}
|
||||
auto lite_kernel = GetLiteKernel(input_tensors, output_tensors, parameter, lite_primitive.get());
|
||||
if (lite_kernel == nullptr) {
|
||||
MS_LOG(ERROR) << "constant_folding schedule node lite kernel nullptr";
|
||||
FreeTensors(&input_tensors, &output_tensors);
|
||||
return nullptr;
|
||||
}
|
||||
auto ret = lite_kernel->Run();
|
||||
if (0 != ret) {
|
||||
FreeTensors(&input_tensors, &output_tensors);
|
||||
MS_LOG(ERROR) << "run kernel failed, name: " << lite_kernel->name();
|
||||
return nullptr;
|
||||
}
|
||||
auto new_parameter = CreateNewParamter(func_graph, output_tensors.front());
|
||||
if (new_parameter == nullptr) {
|
||||
FreeTensors(&input_tensors, &output_tensors);
|
||||
MS_LOG(ERROR) << "CreateNewParamter failed, name: " << lite_kernel->name();
|
||||
return nullptr;
|
||||
}
|
||||
new_parameter->set_name(input_node->fullname_with_scope());
|
||||
any_node->set_input(i, new_parameter);
|
||||
}
|
||||
lite_primitive->InferShape(input_tensors, output_tensors);
|
||||
auto parameter = kernel::PopulateParameter(lite_primitive.get());
|
||||
if (parameter == nullptr) {
|
||||
MS_LOG(ERROR) << "PopulateParameter return nullptr, type: "
|
||||
<< schema::EnumNamePrimitiveType((schema::PrimitiveType) (lite_primitive->Type()));
|
||||
return nullptr;
|
||||
}
|
||||
auto lite_kernel = GetLiteKernel(input_tensors, output_tensors, parameter, lite_primitive.get());
|
||||
if (lite_kernel == nullptr) {
|
||||
MS_LOG(ERROR) << "constant_folding schedule node lite kernel nullptr";
|
||||
FreeTensors(&input_tensors, &output_tensors);
|
||||
return nullptr;
|
||||
}
|
||||
auto ret = lite_kernel->Run();
|
||||
if (0 != ret) {
|
||||
FreeTensors(&input_tensors, &output_tensors);
|
||||
MS_LOG(ERROR) << "run kernel failed, name: " << lite_kernel->name();
|
||||
return nullptr;
|
||||
}
|
||||
// replace cnode by new param
|
||||
if (ReplaceCNode(func_graph, any_node, input_node, output_tensors, i) != lite::RET_OK) {
|
||||
FreeTensors(&input_tensors, &output_tensors);
|
||||
delete (lite_kernel);
|
||||
MS_LOG(ERROR) << "constant_folding replace cnode failed";
|
||||
return nullptr;
|
||||
}
|
||||
FreeTensors(&input_tensors, &output_tensors);
|
||||
delete (lite_kernel);
|
||||
}
|
||||
return any_node;
|
||||
return changed ? any_node : nullptr;
|
||||
}
|
||||
} // namespace mindspore::opt
|
||||
|
|
Loading…
Reference in New Issue