From 958afec3d2f58d44b413164998d0f5aa520592e0 Mon Sep 17 00:00:00 2001 From: Zheng-Bicheng Date: Fri, 12 Jul 2024 18:48:09 +0800 Subject: [PATCH 1/6] update code style --- paddle2onnx/mapper/exporter.cc | 1055 ++++++++++++++++++-------------- paddle2onnx/mapper/exporter.h | 169 ++--- 2 files changed, 671 insertions(+), 553 deletions(-) diff --git a/paddle2onnx/mapper/exporter.cc b/paddle2onnx/mapper/exporter.cc index c60f2b540..ca78a4d15 100644 --- a/paddle2onnx/mapper/exporter.cc +++ b/paddle2onnx/mapper/exporter.cc @@ -28,534 +28,645 @@ #include "paddle2onnx/optimizer/fuse_paddle_conv_bias.h" #include "paddle2onnx/optimizer/fuse_unsqueeze_conv2d_squeeze.h" -namespace paddle2onnx { -MapperHelper* MapperHelper::helper = nullptr; - -void ModelExporter::ExportParameters( - const std::map& params, bool use_initializer) { - for (auto& item : params) { - // TODO(jiangjiajun) I'm not handling use_initializer now, but some day I - // will - auto node = MakeConstant(item.first, item.second); - parameters.push_back(std::move(node)); +namespace paddle2onnx +{ + MapperHelper *MapperHelper::helper = nullptr; + + void ModelExporter::ExportParameters( + const std::map ¶ms, bool use_initializer) + { + for (auto &item : params) + { + // TODO(jiangjiajun) I'm not handling use_initializer now, but some day I + // will + auto node = MakeConstant(item.first, item.second); + parameters.push_back(std::move(node)); + } } -} - -void ModelExporter::UpdateParameters( - const std::map& params) { - for (auto& item : params) { - auto node = MakeConstant(item.first, item.second); - bool updated = false; - for (int i = 0; i < parameters.size(); ++i) { - auto old_node = parameters[i]; - if (old_node->output(0) == item.first) { - parameters.erase(parameters.begin() + i); + + void ModelExporter::UpdateParameters( + const std::map ¶ms) + { + for (auto &item : params) + { + auto node = MakeConstant(item.first, item.second); + bool updated = false; + for (int i = 0; i < parameters.size(); ++i) + { + auto old_node = parameters[i]; + if (old_node->output(0) == item.first) + { + parameters.erase(parameters.begin() + i); + parameters.push_back(std::move(node)); + updated = true; + break; + } + } + if (!updated) + { parameters.push_back(std::move(node)); - updated = true; - break; } } - if (!updated) { - parameters.push_back(std::move(node)); - } } -} - -void ModelExporter::ExportInputOutputs( - const std::vector& input_infos, - const std::vector& output_infos) { - for (auto& item : input_infos) { - auto value_info = MakeValueInfo(item); - inputs.push_back(std::move(value_info)); - } - for (auto& item : output_infos) { - auto value_info = MakeValueInfo(item); - outputs.push_back(std::move(value_info)); + + void ModelExporter::ExportInputOutputs( + const std::vector &input_infos, + const std::vector &output_infos) + { + for (auto &item : input_infos) + { + auto value_info = MakeValueInfo(item); + inputs.push_back(std::move(value_info)); + } + for (auto &item : output_infos) + { + auto value_info = MakeValueInfo(item); + outputs.push_back(std::move(value_info)); + } } -} - -void ModelExporter::CovertCustomOps(const PaddleParser& parser, - OnnxHelper* helper, int64_t block_id, - int64_t op_id) { - auto op = parser.GetOpDesc(block_id, op_id); - std::vector input_strs; - for (auto i_index = 0; i_index < op.inputs_size(); i_index++) { - auto input = op.inputs(i_index); - std::string parameter = input.parameter(); - if (parser.OpHasInput(block_id, op_id, parameter)) { - auto input_info = parser.GetOpInput(block_id, op_id, parameter); - for (auto input : input_info) { - input_strs.push_back(input.name); - helper->MakeValueInfo(input.name, input.dtype, input.shape); + + void ModelExporter::CovertCustomOps(const PaddleParser &parser, + OnnxHelper *helper, int64_t block_id, + int64_t op_id) + { + auto op = parser.GetOpDesc(block_id, op_id); + std::vector input_strs; + for (auto i_index = 0; i_index < op.inputs_size(); i_index++) + { + auto input = op.inputs(i_index); + std::string parameter = input.parameter(); + if (parser.OpHasInput(block_id, op_id, parameter)) + { + auto input_info = parser.GetOpInput(block_id, op_id, parameter); + for (auto input : input_info) + { + input_strs.push_back(input.name); + helper->MakeValueInfo(input.name, input.dtype, input.shape); + } } } - } - std::vector output_strs; - for (auto o_index = 0; o_index < op.outputs_size(); o_index++) { - auto output = op.outputs(o_index); - std::string parameter = output.parameter(); - if (parser.OpHasOutput(block_id, op_id, parameter)) { - auto output_info = parser.GetOpOutput(block_id, op_id, parameter); - for (auto output : output_info) { - output_strs.push_back(output.name); - helper->MakeValueInfo(output.name, output.dtype, output.shape); + std::vector output_strs; + for (auto o_index = 0; o_index < op.outputs_size(); o_index++) + { + auto output = op.outputs(o_index); + std::string parameter = output.parameter(); + if (parser.OpHasOutput(block_id, op_id, parameter)) + { + auto output_info = parser.GetOpOutput(block_id, op_id, parameter); + for (auto output : output_info) + { + output_strs.push_back(output.name); + helper->MakeValueInfo(output.name, output.dtype, output.shape); + } } } } -} -void ModelExporter::ExportOp(const PaddleParser& parser, OnnxHelper* helper, - int32_t opset_version, int64_t block_id, - int64_t op_id, bool verbose) { - _current_exported_num += 1; - auto op = parser.GetOpDesc(block_id, op_id); + void ModelExporter::ExportOp(const PaddleParser &parser, OnnxHelper *helper, + int32_t opset_version, int64_t block_id, + int64_t op_id, bool verbose) + { + _current_exported_num += 1; + auto op = parser.GetOpDesc(block_id, op_id); #ifdef PADDLE2ONNX_DEBUG - P2OLogger(true) << "---Converting operator: " << op.type() << " ---" - << std::endl; + P2OLogger(true) << "---Converting operator: " << op.type() << " ---" + << std::endl; #endif - if (op.type() == "while") { - return ExportLoop(parser, helper, opset_version, block_id, op_id, verbose); - } + if (op.type() == "while") + { + return ExportLoop(parser, helper, opset_version, block_id, op_id, verbose); + } - auto mapper = MapperHelper::Get()->CreateMapper(op.type(), parser, helper, block_id, op_id); - mapper->deploy_backend = _deploy_backend; + auto mapper = MapperHelper::Get()->CreateMapper(op.type(), parser, helper, block_id, op_id); + mapper->deploy_backend = _deploy_backend; #ifdef PADDLE2ONNX_DEBUG - P2OLogger(true) << "Mapper Name: " << mapper->Name() << std::endl; + P2OLogger(true) << "Mapper Name: " << mapper->Name() << std::endl; #endif - mapper->Run(); - delete mapper; + mapper->Run(); + delete mapper; #ifdef PADDLE2ONNX_DEBUG - P2OLogger(true) << "---Converting operator: " << op.type() << " done---" - << std::endl; + P2OLogger(true) << "---Converting operator: " << op.type() << " done---" + << std::endl; #endif -} - -void ModelExporter::ProcessGraphDumplicateNames( - std::vector>* parameters, - std::vector>* inputs, - std::vector>* outputs, - std::vector>* nodes, - std::map* quantize_info) { - // process dumplicate tensor names - std::map renamer; - std::set tensor_names; - for (auto& item : *parameters) { - for (size_t i = 0; i < item->output_size(); ++i) { - if (tensor_names.find(item->output(i)) != tensor_names.end()) { - Assert(false, "There's dumplicate names in exported parameters."); - } - tensor_names.insert(item->output(i)); - } } - for (auto& item : *inputs) { - if (tensor_names.find(item->name()) != tensor_names.end()) { - Assert(false, "There's dumplicate names:" + item->name() + - " in exported parameters and inputs."); - } - tensor_names.insert(item->name()); - } - for (auto& item : *nodes) { - // update node inputs - for (size_t i = 0; i < item->input_size(); ++i) { - if (renamer.find(item->input(i)) != renamer.end()) { - auto updated_name = renamer[item->input(i)]; - while (renamer.find(updated_name) != renamer.end()) { - updated_name = renamer[updated_name]; + + void ModelExporter::ProcessGraphDumplicateNames( + std::vector> *parameters, + std::vector> *inputs, + std::vector> *outputs, + std::vector> *nodes, + std::map *quantize_info) + { + // process dumplicate tensor names + std::map renamer; + std::set tensor_names; + for (auto &item : *parameters) + { + for (size_t i = 0; i < item->output_size(); ++i) + { + if (tensor_names.find(item->output(i)) != tensor_names.end()) + { + Assert(false, "There's dumplicate names in exported parameters."); } - *(item->mutable_input(i)) = updated_name; + tensor_names.insert(item->output(i)); } } - // if there's dumplicate name - // will generate new name and replace it - for (size_t i = 0; i < item->output_size(); ++i) { - if (tensor_names.find(item->output(i)) != tensor_names.end()) { - std::string renamed_tensor_name = item->output(i); - while (renamer.find(renamed_tensor_name) != renamer.end()) { - renamed_tensor_name = renamer[renamed_tensor_name]; + for (auto &item : *inputs) + { + if (tensor_names.find(item->name()) != tensor_names.end()) + { + Assert(false, "There's dumplicate names:" + item->name() + + " in exported parameters and inputs."); + } + tensor_names.insert(item->name()); + } + for (auto &item : *nodes) + { + // update node inputs + for (size_t i = 0; i < item->input_size(); ++i) + { + if (renamer.find(item->input(i)) != renamer.end()) + { + auto updated_name = renamer[item->input(i)]; + while (renamer.find(updated_name) != renamer.end()) + { + updated_name = renamer[updated_name]; + } + *(item->mutable_input(i)) = updated_name; } - auto new_tensor_name = - MapperHelper::Get()->GenName(renamed_tensor_name); - P2OLogger() << "Find dumplicate output name '" << renamed_tensor_name - << "', it will rename to '" << new_tensor_name << "'." - << std::endl; - if (quantize_info && - quantize_info->find(renamed_tensor_name) != quantize_info->end()) { - (*quantize_info)[new_tensor_name] = - (*quantize_info)[renamed_tensor_name]; + } + // if there's dumplicate name + // will generate new name and replace it + for (size_t i = 0; i < item->output_size(); ++i) + { + if (tensor_names.find(item->output(i)) != tensor_names.end()) + { + std::string renamed_tensor_name = item->output(i); + while (renamer.find(renamed_tensor_name) != renamer.end()) + { + renamed_tensor_name = renamer[renamed_tensor_name]; + } + auto new_tensor_name = + MapperHelper::Get()->GenName(renamed_tensor_name); + P2OLogger() << "Find dumplicate output name '" << renamed_tensor_name + << "', it will rename to '" << new_tensor_name << "'." + << std::endl; + if (quantize_info && + quantize_info->find(renamed_tensor_name) != quantize_info->end()) + { + (*quantize_info)[new_tensor_name] = + (*quantize_info)[renamed_tensor_name]; + } + *(item->mutable_output(i)) = new_tensor_name; + renamer[renamed_tensor_name] = new_tensor_name; } - *(item->mutable_output(i)) = new_tensor_name; - renamer[renamed_tensor_name] = new_tensor_name; + tensor_names.insert(item->output(i)); } - tensor_names.insert(item->output(i)); } - } - for (auto& item : *outputs) { - if (renamer.find(item->name()) != renamer.end()) { - auto updated_name = renamer[item->name()]; - while (renamer.find(updated_name) != renamer.end()) { - updated_name = renamer[updated_name]; + for (auto &item : *outputs) + { + if (renamer.find(item->name()) != renamer.end()) + { + auto updated_name = renamer[item->name()]; + while (renamer.find(updated_name) != renamer.end()) + { + updated_name = renamer[updated_name]; + } + item->set_name(updated_name); } - item->set_name(updated_name); } } -} - -void ModelExporter::SaveExternalData(::ONNX_NAMESPACE::GraphProto* graph, - const std::string& external_file_path, - bool* save_external) { - P2OLogger() << "The exported ONNX model is bigger than 2G, external data " - "will save to file: " - << external_file_path << std::endl; - std::string file_name = GetFilenameFromPath(external_file_path); - if (save_external) { - *save_external = true; - } - std::fstream f(external_file_path, std::ios::out); - Assert(f.is_open(), "Failed to open: " + external_file_path + - " file to save external data"); - for (auto index = 0; index < graph->node_size(); index++) { - auto node = graph->mutable_node(index); - if (node->op_type() != "Constant") { - continue; - } - for (auto i = 0; i < node->attribute_size(); i++) { - auto attr = node->mutable_attribute(i); - if (attr->name() != "value") { - continue; - } - auto tensor = attr->mutable_t(); - if (tensor->raw_data().size() <= 128) { + void ModelExporter::SaveExternalData(::ONNX_NAMESPACE::GraphProto *graph, + const std::string &external_file_path, + bool *save_external) + { + P2OLogger() << "The exported ONNX model is bigger than 2G, external data " + "will save to file: " + << external_file_path << std::endl; + std::string file_name = GetFilenameFromPath(external_file_path); + if (save_external) + { + *save_external = true; + } + std::fstream f(external_file_path, std::ios::out); + Assert(f.is_open(), "Failed to open: " + external_file_path + + " file to save external data"); + for (auto index = 0; index < graph->node_size(); index++) + { + auto node = graph->mutable_node(index); + if (node->op_type() != "Constant") + { continue; } + for (auto i = 0; i < node->attribute_size(); i++) + { + auto attr = node->mutable_attribute(i); + if (attr->name() != "value") + { + continue; + } + auto tensor = attr->mutable_t(); + + if (tensor->raw_data().size() <= 128) + { + continue; + } - tensor->set_data_location(ONNX_NAMESPACE::TensorProto::EXTERNAL); - auto external_data = tensor->add_external_data(); - external_data->set_key("location"); - external_data->set_value(file_name); - - external_data = tensor->add_external_data(); - external_data->set_key("offset"); - f.seekg(0, std::ios::end); - int64_t offset = f.tellg(); - external_data->set_value(std::to_string(offset)); - auto raw_data = tensor->raw_data(); - f << raw_data; - external_data = tensor->add_external_data(); - external_data->set_key("length"); - int64_t raw_datas_size = raw_data.size(); - external_data->set_value(std::to_string(raw_datas_size)); - tensor->clear_raw_data(); + tensor->set_data_location(ONNX_NAMESPACE::TensorProto::EXTERNAL); + auto external_data = tensor->add_external_data(); + external_data->set_key("location"); + external_data->set_value(file_name); + + external_data = tensor->add_external_data(); + external_data->set_key("offset"); + f.seekg(0, std::ios::end); + int64_t offset = f.tellg(); + external_data->set_value(std::to_string(offset)); + auto raw_data = tensor->raw_data(); + f << raw_data; + external_data = tensor->add_external_data(); + external_data->set_key("length"); + int64_t raw_datas_size = raw_data.size(); + external_data->set_value(std::to_string(raw_datas_size)); + tensor->clear_raw_data(); + } + } + f.close(); + } + void ModelExporter::ONNXChecker(const ONNX_NAMESPACE::ModelProto &model, + const bool &verbose) + { + // TODO(jiangjiajun) + // If we need to integrate with framework + // this check will return a information + // to let framework know the conversion is + // pass or fail + try + { + // ONNX_NAMESPACE::checker::check_model(*(model.get())); + ONNX_NAMESPACE::checker::check_model(model); + } + catch (const std::exception &e) + { + P2OLogger(verbose) << "The exported ONNX model is invalid." << std::endl; + P2OLogger(verbose) << "Model checker error log: " << e.what() << std::endl; + } + P2OLogger(verbose) << "PaddlePaddle model is exported as ONNX format now." + << std::endl; + } + + std::string ModelExporter::Run(const PaddleParser &parser, + int opset_version, + bool auto_upgrade_opset, + bool verbose, + bool enable_onnx_checker, + bool enable_experimental_op, + bool enable_optimize, + const std::string &deploy_backend, + std::string *calibration_cache, + const std::string &external_file, + bool *save_external, + bool export_fp16_model, + std::vector disable_fp16_op_types) + { + _deploy_backend = deploy_backend; + _helper.SetOpsetVersion(opset_version); + _total_ops_num = 0; + _current_exported_num = 0; + for (auto i = 0; i < parser.NumOfBlocks(); ++i) + { + _total_ops_num += parser.NumOfOps(i); + } + _helper.nodes.reserve(_total_ops_num * 3); + Assert(opset_version <= MAX_ONNX_OPSET_VERSION && opset_version >= 7, + "Paddle2ONNX now only support opset version in range of [7, " + + std::to_string(MAX_ONNX_OPSET_VERSION) + "]."); + _helper.Clear(); + inputs.clear(); + outputs.clear(); + parameters.clear(); + + // clear name_counter + // this use to generate unique name + // for intermdiate + // while converting all the op + MapperHelper::Get()->ClearNameCounter(); + + std::set unsupported_ops; + if (!CheckIfOpSupported(parser, &unsupported_ops, enable_experimental_op)) + { + auto logger = P2OLogger(); + logger << "Oops, there are some operators not supported yet, including "; + for (auto &item : unsupported_ops) + { + logger << item << ","; + } + logger << std::endl; + Assert(1 == 0, + "Due to the unsupported operators, the conversion is aborted."); } - } - f.close(); -} -void ModelExporter::ONNXChecker(const ONNX_NAMESPACE::ModelProto& model, - const bool& verbose) { - // TODO(jiangjiajun) - // If we need to integrate with framework - // this check will return a information - // to let framework know the conversion is - // pass or fail - try { - // ONNX_NAMESPACE::checker::check_model(*(model.get())); - ONNX_NAMESPACE::checker::check_model(model); - } catch (const std::exception& e) { - P2OLogger(verbose) << "The exported ONNX model is invalid." << std::endl; - P2OLogger(verbose) << "Model checker error log: " << e.what() << std::endl; - } - P2OLogger(verbose) << "PaddlePaddle model is exported as ONNX format now." - << std::endl; -} - -std::string ModelExporter::Run( - const PaddleParser& parser, int opset_version, bool auto_upgrade_opset, - bool verbose, bool enable_onnx_checker, bool enable_experimental_op, - bool enable_optimize, const std::string& deploy_backend, - std::string* calibration_cache, const std::string& external_file, - bool* save_external, bool export_fp16_model, - std::vector disable_fp16_op_types) { - _deploy_backend = deploy_backend; - _helper.SetOpsetVersion(opset_version); - _total_ops_num = 0; - _current_exported_num = 0; - for (auto i = 0; i < parser.NumOfBlocks(); ++i) { - _total_ops_num += parser.NumOfOps(i); - } - _helper.nodes.reserve(_total_ops_num * 3); - Assert(opset_version <= MAX_ONNX_OPSET_VERSION && opset_version >= 7, - "Paddle2ONNX now only support opset version in range of [7, " + - std::to_string(MAX_ONNX_OPSET_VERSION) + "]."); - _helper.Clear(); - inputs.clear(); - outputs.clear(); - parameters.clear(); - - // clear name_counter - // this use to generate unique name - // for intermdiate - // while converting all the op - MapperHelper::Get()->ClearNameCounter(); - - std::set unsupported_ops; - if (!CheckIfOpSupported(parser, &unsupported_ops, enable_experimental_op)) { - auto logger = P2OLogger(); - logger << "Oops, there are some operators not supported yet, including "; - for (auto& item : unsupported_ops) { - logger << item << ","; - } - logger << std::endl; - Assert(1 == 0, - "Due to the unsupported operators, the conversion is aborted."); - } - int32_t min_opset = GetMinOpset(parser, verbose); - if (min_opset < 0) { - Assert(false, - "Model exporting failed, you can report this problem to " - "https://github.com/PaddlePaddle/Paddle2ONNX.git."); - } - if (!auto_upgrade_opset) { - if (min_opset > opset_version) { - P2OLogger() << "This PaddlePaddle model is not able to export to ONNX " - "with opset_version=" - << opset_version << ", please set the opset_version to " - << min_opset << " or higher for successfully conversion." - << std::endl; + int32_t min_opset = GetMinOpset(parser, verbose); + if (min_opset < 0) + { Assert(false, - "Due to opset version, the model exporting is aborted, please set " - "a higher opset_version or set auto_upgrade_opset=true."); + "Model exporting failed, you can report this problem to " + "https://github.com/PaddlePaddle/Paddle2ONNX.git."); } - } else { - if (min_opset > opset_version) { - P2OLogger() << "Opset version will change to " << min_opset << " from " - << opset_version << std::endl; - opset_version = min_opset; + if (!auto_upgrade_opset) + { + if (min_opset > opset_version) + { + P2OLogger() << "This PaddlePaddle model is not able to export to ONNX " + "with opset_version=" + << opset_version << ", please set the opset_version to " + << min_opset << " or higher for successfully conversion." + << std::endl; + Assert(false, + "Due to opset version, the model exporting is aborted, please set " + "a higher opset_version or set auto_upgrade_opset=true."); + } + } + else + { + if (min_opset > opset_version) + { + P2OLogger() << "Opset version will change to " << min_opset << " from " + << opset_version << std::endl; + opset_version = min_opset; + } + } + _helper.SetOpsetVersion(opset_version); + P2OLogger(verbose) << "Use opset_version = " << _helper.GetOpsetVersion() + << " for ONNX export." << std::endl; + ExportParameters(parser.params); + ExportInputOutputs(parser.inputs, parser.outputs); + + // Only convert blocks 0 now + // because control flow is not supported yet + for (auto i = 0; i < parser.NumOfOps(0); ++i) + { + auto op = parser.GetOpDesc(0, i); + if (op.type() == "feed") + { + continue; + } + else if (op.type() == "fetch") + { + continue; + } + ExportOp(parser, &_helper, opset_version, 0, i, verbose); } - } - _helper.SetOpsetVersion(opset_version); - P2OLogger(verbose) << "Use opset_version = " << _helper.GetOpsetVersion() - << " for ONNX export." << std::endl; - ExportParameters(parser.params); - ExportInputOutputs(parser.inputs, parser.outputs); - - // Only convert blocks 0 now - // because control flow is not supported yet - for (auto i = 0; i < parser.NumOfOps(0); ++i) { - auto op = parser.GetOpDesc(0, i); - if (op.type() == "feed") { - continue; - } else if (op.type() == "fetch") { - continue; - } - ExportOp(parser, &_helper, opset_version, 0, i, verbose); - } - - // construct a onnx model proto - auto ir_version = _helper.GetIRVersion(); - auto model = std::make_shared(); - model->set_ir_version(ir_version); - - auto graph = model->mutable_graph(); - graph->set_name("Model from PaddlePaddle."); - - auto opset_id = model->add_opset_import(); - opset_id->set_domain(""); - opset_id->set_version(opset_version); - - ProcessGraphDumplicateNames(¶meters, &inputs, &outputs, &_helper.nodes, - &_helper.quantize_info); - if (parser.is_quantized_model) { - quantize_model_processer.ProcessQuantizeModel( - ¶meters, &inputs, &outputs, &_helper.nodes, &_helper, - deploy_backend, parser, calibration_cache); - // Update int8 weights in quantized OP to float32 - UpdateParameters(_helper.updated_params); - } - for (auto& item : parameters) { - *(graph->add_node()) = *(item.get()); - } - for (auto& item : inputs) { - *(graph->add_input()) = *(item.get()); - } - for (auto& item : _helper.nodes) { - *(graph->add_node()) = (*item.get()); - } - for (auto& item : outputs) { - *(graph->add_output()) = (*item.get()); - } - for (auto& item : _helper.value_infos) { - *(graph->add_value_info()) = (*item.get()); - } + // construct a onnx model proto + auto ir_version = _helper.GetIRVersion(); + auto model = std::make_shared(); + model->set_ir_version(ir_version); + + auto graph = model->mutable_graph(); + graph->set_name("Model from PaddlePaddle."); + + auto opset_id = model->add_opset_import(); + opset_id->set_domain(""); + opset_id->set_version(opset_version); + + ProcessGraphDumplicateNames(¶meters, &inputs, &outputs, &_helper.nodes, + &_helper.quantize_info); + if (parser.is_quantized_model) + { + quantize_model_processer.ProcessQuantizeModel( + ¶meters, &inputs, &outputs, &_helper.nodes, &_helper, + deploy_backend, parser, calibration_cache); + // Update int8 weights in quantized OP to float32 + UpdateParameters(_helper.updated_params); + } - ONNX_NAMESPACE::ModelProto onnx_model; - std::string out; - if (enable_optimize) { - onnx_model = Optimize(*(model.get())); - } else { - onnx_model = *model.get(); - } + for (auto &item : parameters) + { + *(graph->add_node()) = *(item.get()); + } + for (auto &item : inputs) + { + *(graph->add_input()) = *(item.get()); + } + for (auto &item : _helper.nodes) + { + *(graph->add_node()) = (*item.get()); + } + for (auto &item : outputs) + { + *(graph->add_output()) = (*item.get()); + } + for (auto &item : _helper.value_infos) + { + *(graph->add_value_info()) = (*item.get()); + } - // convert fp32 model to fp16 - if (export_fp16_model) { - P2OLogger(verbose) << "Convert FP32 ONNX model to FP16." << std::endl; - ConvertFp32ToFp16 convert; - convert.AddDisabledOpTypes(disable_fp16_op_types); - convert.Convert(&onnx_model); - } + ONNX_NAMESPACE::ModelProto onnx_model; + std::string out; + if (enable_optimize) + { + onnx_model = Optimize(*(model.get())); + } + else + { + onnx_model = *model.get(); + } - // save external data file for big model - std::string external_data_file; - if (onnx_model.ByteSizeLong() > INT_MAX) { - if (external_file.empty()) { - external_data_file = "external_data"; - } else { - external_data_file = external_file; + // convert fp32 model to fp16 + if (export_fp16_model) + { + P2OLogger(verbose) << "Convert FP32 ONNX model to FP16." << std::endl; + ConvertFp32ToFp16 convert; + convert.AddDisabledOpTypes(disable_fp16_op_types); + convert.Convert(&onnx_model); } - } - if (external_data_file.size()) { - SaveExternalData(onnx_model.mutable_graph(), external_data_file, - save_external); - } - // check model - if (enable_onnx_checker) { - ONNXChecker(onnx_model, verbose); - } - if (!onnx_model.SerializeToString(&out)) { - P2OLogger(verbose) - << "Error happenedd while optimizing the exported ONNX model." - << std::endl; - return ""; - } - return out; -} - -bool ModelExporter::CheckIfOpSupported(const PaddleParser& parser, - std::set* unsupported_ops, - bool enable_experimental_op) { - unsupported_ops->clear(); - for (auto i = 0; i < parser.NumOfBlocks(); ++i) { - for (auto j = 0; j < parser.NumOfOps(i); ++j) { - auto op = parser.GetOpDesc(i, j); - if (op.type() == "feed" || op.type() == "fetch") { - continue; + // save external data file for big model + std::string external_data_file; + if (onnx_model.ByteSizeLong() > INT_MAX) + { + if (external_file.empty()) + { + external_data_file = "external_data"; } - if (op.type() == "while" && enable_experimental_op) { - if (!IsLoopSupported(parser, i, j)) { - unsupported_ops->insert("while"); - } - continue; + else + { + external_data_file = external_file; } - if (!MapperHelper::Get()->IsRegistered(op.type())) { - unsupported_ops->insert(op.type()); - } else if (!enable_experimental_op) { - auto mapper = MapperHelper::Get()->CreateMapper(op.type(), parser, - &_helper, i, j); - if (mapper->IsExperimentalOp()) { + } + if (external_data_file.size()) + { + SaveExternalData(onnx_model.mutable_graph(), external_data_file, + save_external); + } + // check model + if (enable_onnx_checker) + { + ONNXChecker(onnx_model, verbose); + } + + if (!onnx_model.SerializeToString(&out)) + { + P2OLogger(verbose) + << "Error happenedd while optimizing the exported ONNX model." + << std::endl; + return ""; + } + return out; + } + + bool ModelExporter::CheckIfOpSupported(const PaddleParser &parser, + std::set *unsupported_ops, + bool enable_experimental_op) + { + unsupported_ops->clear(); + for (auto i = 0; i < parser.NumOfBlocks(); ++i) + { + for (auto j = 0; j < parser.NumOfOps(i); ++j) + { + auto op = parser.GetOpDesc(i, j); + if (op.type() == "feed" || op.type() == "fetch") + { + continue; + } + if (op.type() == "while" && enable_experimental_op) + { + if (!IsLoopSupported(parser, i, j)) + { + unsupported_ops->insert("while"); + } + continue; + } + if (!MapperHelper::Get()->IsRegistered(op.type())) + { unsupported_ops->insert(op.type()); } - delete mapper; + else if (!enable_experimental_op) + { + auto mapper = MapperHelper::Get()->CreateMapper(op.type(), parser, + &_helper, i, j); + if (mapper->IsExperimentalOp()) + { + unsupported_ops->insert(op.type()); + } + delete mapper; + } } } - } - return (unsupported_ops->size() == 0); -} - -int32_t ModelExporter::GetMinOpset(const PaddleParser& parser, bool verbose) { - int32_t opset_version = _helper.GetOpsetVersion(); - int32_t max_opset = 7; - bool exportable = true; - // Record the number of ops that need to be converted - int converted_op_num = 0; - std::set verbose_log; - for (auto i = 0; i < parser.NumOfBlocks(); ++i) { - for (auto j = 0; j < parser.NumOfOps(i); ++j) { - auto op = parser.GetOpDesc(i, j); - if (op.type() == "feed" || op.type() == "fetch") { - continue; - } - converted_op_num += 1; - int current_min_opset = 7; - if (op.type() == "while") { - P2OLogger() << "Detected there's control flow 'while' op in your " - "model, this requires the minimal opset version of 13." - << std::endl; - current_min_opset = 13; - } else { - auto mapper = MapperHelper::Get()->CreateMapper(op.type(), parser, &_helper, i, j); - current_min_opset = mapper->GetMinOpset(verbose); - delete mapper; - } - if (current_min_opset < 0) { - exportable = false; - P2OLogger(verbose) << "Due to the operator: " << op.type() - << ", this model cannot be exported to ONNX." - << std::endl; - } else if (current_min_opset > max_opset) { - max_opset = current_min_opset; - if (verbose && current_min_opset > opset_version) { - verbose_log.insert("Due to the operator: " + op.type() + - ", requires opset_version >= " + - std::to_string(current_min_opset) + "."); + return (unsupported_ops->size() == 0); + } + + int32_t ModelExporter::GetMinOpset(const PaddleParser &parser, bool verbose) + { + int32_t opset_version = _helper.GetOpsetVersion(); + int32_t max_opset = 7; + bool exportable = true; + // Record the number of ops that need to be converted + int converted_op_num = 0; + std::set verbose_log; + for (auto i = 0; i < parser.NumOfBlocks(); ++i) + { + for (auto j = 0; j < parser.NumOfOps(i); ++j) + { + auto op = parser.GetOpDesc(i, j); + if (op.type() == "feed" || op.type() == "fetch") + { + continue; + } + converted_op_num += 1; + int current_min_opset = 7; + if (op.type() == "while") + { + P2OLogger() << "Detected there's control flow 'while' op in your " + "model, this requires the minimal opset version of 13." + << std::endl; + current_min_opset = 13; + } + else + { + auto mapper = MapperHelper::Get()->CreateMapper(op.type(), parser, &_helper, i, j); + current_min_opset = mapper->GetMinOpset(verbose); + delete mapper; + } + if (current_min_opset < 0) + { + exportable = false; + P2OLogger(verbose) << "Due to the operator: " << op.type() + << ", this model cannot be exported to ONNX." + << std::endl; + } + else if (current_min_opset > max_opset) + { + max_opset = current_min_opset; + if (verbose && current_min_opset > opset_version) + { + verbose_log.insert("Due to the operator: " + op.type() + + ", requires opset_version >= " + + std::to_string(current_min_opset) + "."); + } } } } - } - if (verbose) { - for (auto iter = verbose_log.begin(); iter != verbose_log.end(); ++iter) { - P2OLogger() << *iter << std::endl; + if (verbose) + { + for (auto iter = verbose_log.begin(); iter != verbose_log.end(); ++iter) + { + P2OLogger() << *iter << std::endl; + } } - } - // Here we put some checks to make sure - // paddle2onnx could compatible with - // other version of onnx - int32_t max_support_opset = MAX_ONNX_OPSET_VERSION; - if (exportable && (max_opset > MAX_ONNX_OPSET_VERSION)) { - exportable = false; - P2OLogger() << "[ERROR] The compiled ONNX version only supports opset 7~" - << MAX_ONNX_OPSET_VERSION - << ", but now this model need as least opset " << max_opset - << ", please compile with higher version of ONNX." << std::endl; - } - if (exportable) { - return max_opset; - } + // Here we put some checks to make sure + // paddle2onnx could compatible with + // other version of onnx + int32_t max_support_opset = MAX_ONNX_OPSET_VERSION; + if (exportable && (max_opset > MAX_ONNX_OPSET_VERSION)) + { + exportable = false; + P2OLogger() << "[ERROR] The compiled ONNX version only supports opset 7~" + << MAX_ONNX_OPSET_VERSION + << ", but now this model need as least opset " << max_opset + << ", please compile with higher version of ONNX." << std::endl; + } + if (exportable) + { + return max_opset; + } - return -1; -} - -ONNX_NAMESPACE::ModelProto ModelExporter::Optimize( - const ONNX_NAMESPACE::ModelProto& model) { - ONNX_NAMESPACE::optimization::Optimizer::passes - .registerPass(); - ONNX_NAMESPACE::optimization::Optimizer::passes - .registerPass(); - ONNX_NAMESPACE::optimization::Optimizer::passes - .registerPass(); - ONNX_NAMESPACE::optimization::Optimizer::passes - .registerPass(); - ONNX_NAMESPACE::optimization::Optimizer::passes - .registerPass(); - ONNX_NAMESPACE::optimization::Optimizer::passes - .registerPass(); - std::vector passes = {"eliminate_identity", - "eliminate_deadend", - "eliminate_deadend", - "fuse_constant_reshape", - "fuse_constant_unsqueeze", - "fuse_paddle_conv_bias", - "fuse_consecutive_transposes", - "eliminate_non_transpose", - "fuse_matmul_add_bias_into_gemm", - "eliminate_identity", - "eliminate_deadend", - "eliminate_unused_initializer"}; - return ONNX_NAMESPACE::optimization::Optimize(model, passes); -} - -} // namespace paddle2onnx + return -1; + } + + ONNX_NAMESPACE::ModelProto ModelExporter::Optimize( + const ONNX_NAMESPACE::ModelProto &model) + { + ONNX_NAMESPACE::optimization::Optimizer::passes + .registerPass(); + ONNX_NAMESPACE::optimization::Optimizer::passes + .registerPass(); + ONNX_NAMESPACE::optimization::Optimizer::passes + .registerPass(); + ONNX_NAMESPACE::optimization::Optimizer::passes + .registerPass(); + ONNX_NAMESPACE::optimization::Optimizer::passes + .registerPass(); + ONNX_NAMESPACE::optimization::Optimizer::passes + .registerPass(); + std::vector passes = {"eliminate_identity", + "eliminate_deadend", + "eliminate_deadend", + "fuse_constant_reshape", + "fuse_constant_unsqueeze", + "fuse_paddle_conv_bias", + "fuse_consecutive_transposes", + "eliminate_non_transpose", + "fuse_matmul_add_bias_into_gemm", + "eliminate_identity", + "eliminate_deadend", + "eliminate_unused_initializer"}; + return ONNX_NAMESPACE::optimization::Optimize(model, passes); + } + +} // namespace paddle2onnx diff --git a/paddle2onnx/mapper/exporter.h b/paddle2onnx/mapper/exporter.h index 1f0f4d5a3..775c61306 100644 --- a/paddle2onnx/mapper/exporter.h +++ b/paddle2onnx/mapper/exporter.h @@ -28,92 +28,99 @@ #define PATH_SEP "/" #endif -inline std::string GetFilenameFromPath(const std::string& path) { +inline std::string GetFilenameFromPath(const std::string &path) +{ auto pos = path.find_last_of(PATH_SEP); - if (pos == std::string::npos) { + if (pos == std::string::npos) + { return path; } return path.substr(pos + 1); } -namespace paddle2onnx { - -struct ModelExporter { - private: - std::vector> parameters; - std::vector> inputs; - std::vector> outputs; - // The _deploy_backend will pass to Mapper to influence the conversion - std::string _deploy_backend = "onnxruntime"; - OnnxHelper _helper; - int32_t _total_ops_num = 0; - int32_t _current_exported_num = 0; - - void ExportParameters(const std::map& params, - bool use_initializer = false); - - // Update constant node in parameters. When process quantize model, the weight - // dtype may be int8, it should be convet to float32 and use this function to - // update converted params. - void UpdateParameters(const std::map& params); - void ExportInputOutputs(const std::vector& input_infos, - const std::vector& output_infos); - void ExportOp(const PaddleParser& parser, OnnxHelper* helper, - int32_t opset_version, int64_t block_id, int64_t op_id, - bool verbose); - bool IsLoopSupported(const PaddleParser& parser, const int64_t& block_id, - const int64_t& op_id); - void ExportLoop(const PaddleParser& parser, OnnxHelper* helper, +namespace paddle2onnx +{ + + struct ModelExporter + { + private: + std::vector> parameters; + std::vector> inputs; + std::vector> outputs; + // The _deploy_backend will pass to Mapper to influence the conversion + std::string _deploy_backend = "onnxruntime"; + OnnxHelper _helper; + int32_t _total_ops_num = 0; + int32_t _current_exported_num = 0; + + void ExportParameters(const std::map ¶ms, + bool use_initializer = false); + + // Update constant node in parameters. When process quantize model, the weight + // dtype may be int8, it should be convet to float32 and use this function to + // update converted params. + void UpdateParameters(const std::map ¶ms); + void ExportInputOutputs(const std::vector &input_infos, + const std::vector &output_infos); + void ExportOp(const PaddleParser &parser, OnnxHelper *helper, int32_t opset_version, int64_t block_id, int64_t op_id, bool verbose); - void CovertCustomOps(const PaddleParser& parser, OnnxHelper* helper, - int64_t block_id, int64_t op_id); - ONNX_NAMESPACE::ModelProto Optimize(const ONNX_NAMESPACE::ModelProto& model); - - public: - QuantizeModelProcessor quantize_model_processer; - // Get a proper opset version in range of [7, 16] - // Also will check the model is convertable, this will include 2 parts - // 1. is the op convert function implemented - // 2. is the op convertable(some cases may not be able to convert) - // If the model is not convertable, return -1 - int32_t GetMinOpset(const PaddleParser& parser, bool verbose = false); - - // // Remove isolated nodes in onnx model - // void RemoveIsolatedNodes( - // std::vector>* parameters, - // std::vector>* inputs, - // std::vector>* outputs, - // std::vector>* nodes); - // Process dumplicate tensor names in paddle model - void ProcessGraphDumplicateNames( - std::vector>* parameters, - std::vector>* inputs, - std::vector>* outputs, - std::vector>* nodes, - std::map* quantize_info = nullptr); - - bool CheckIfOpSupported(const PaddleParser& parser, - std::set* unsupported_ops, - bool enable_experimental_op); - - void SaveExternalData(ONNX_NAMESPACE::GraphProto* graph, - const std::string& external_file_path, - bool* save_external = nullptr); - - void ONNXChecker(const ONNX_NAMESPACE::ModelProto& model, - const bool& verbose); - - std::string Run(const PaddleParser& parser, int opset_version = 9, - bool auto_upgrade_opset = true, bool verbose = false, - bool enable_onnx_checker = true, - bool enable_experimental_op = false, - bool enable_optimize = true, - const std::string& deploy_backend = "onnxruntime", - std::string* calibration_cache = nullptr, - const std::string& external_file = "", - bool* save_external = nullptr, bool export_fp16_model = false, - std::vector disable_fp16_op_types = {}); -}; - -} // namespace paddle2onnx + bool IsLoopSupported(const PaddleParser &parser, const int64_t &block_id, + const int64_t &op_id); + void ExportLoop(const PaddleParser &parser, OnnxHelper *helper, + int32_t opset_version, int64_t block_id, int64_t op_id, + bool verbose); + void CovertCustomOps(const PaddleParser &parser, OnnxHelper *helper, + int64_t block_id, int64_t op_id); + ONNX_NAMESPACE::ModelProto Optimize(const ONNX_NAMESPACE::ModelProto &model); + + public: + QuantizeModelProcessor quantize_model_processer; + // Get a proper opset version in range of [7, 16] + // Also will check the model is convertable, this will include 2 parts + // 1. is the op convert function implemented + // 2. is the op convertable(some cases may not be able to convert) + // If the model is not convertable, return -1 + int32_t GetMinOpset(const PaddleParser &parser, bool verbose = false); + + // // Remove isolated nodes in onnx model + // void RemoveIsolatedNodes( + // std::vector>* parameters, + // std::vector>* inputs, + // std::vector>* outputs, + // std::vector>* nodes); + // Process dumplicate tensor names in paddle model + void ProcessGraphDumplicateNames( + std::vector> *parameters, + std::vector> *inputs, + std::vector> *outputs, + std::vector> *nodes, + std::map *quantize_info = nullptr); + + bool CheckIfOpSupported(const PaddleParser &parser, + std::set *unsupported_ops, + bool enable_experimental_op); + + void SaveExternalData(ONNX_NAMESPACE::GraphProto *graph, + const std::string &external_file_path, + bool *save_external = nullptr); + + void ONNXChecker(const ONNX_NAMESPACE::ModelProto &model, + const bool &verbose); + + std::string Run(const PaddleParser &parser, + int opset_version = 9, + bool auto_upgrade_opset = true, + bool verbose = false, + bool enable_onnx_checker = true, + bool enable_experimental_op = false, + bool enable_optimize = true, + const std::string &deploy_backend = "onnxruntime", + std::string *calibration_cache = nullptr, + const std::string &external_file = "", + bool *save_external = nullptr, + bool export_fp16_model = false, + std::vector disable_fp16_op_types = {}); + }; + +} // namespace paddle2onnx From 701fc91cde28092efd60b2b225499c5fa1a8e97e Mon Sep 17 00:00:00 2001 From: Zheng-Bicheng Date: Fri, 12 Jul 2024 19:32:23 +0800 Subject: [PATCH 2/6] update code style --- paddle2onnx/mapper/exporter.cc | 103 ++++++++++++--------------------- 1 file changed, 36 insertions(+), 67 deletions(-) diff --git a/paddle2onnx/mapper/exporter.cc b/paddle2onnx/mapper/exporter.cc index ca78a4d15..a4f042440 100644 --- a/paddle2onnx/mapper/exporter.cc +++ b/paddle2onnx/mapper/exporter.cc @@ -369,44 +369,47 @@ namespace paddle2onnx "Due to the unsupported operators, the conversion is aborted."); } + // Create onnx model + auto model = std::make_shared(); + + // Set the Opset Version of the ONNX model. + bool opset_is_legal = true; int32_t min_opset = GetMinOpset(parser, verbose); - if (min_opset < 0) - { - Assert(false, - "Model exporting failed, you can report this problem to " - "https://github.com/PaddlePaddle/Paddle2ONNX.git."); + if(min_opset < 7 || min_opset >= MAX_ONNX_OPSET_VERSION) { + P2OLogger() << "The Opset Version must be between 7 and " << MAX_ONNX_OPSET_VERSION - 1 << std::endl; + opset_is_legal = false; } if (!auto_upgrade_opset) { if (min_opset > opset_version) { - P2OLogger() << "This PaddlePaddle model is not able to export to ONNX " - "with opset_version=" - << opset_version << ", please set the opset_version to " - << min_opset << " or higher for successfully conversion." - << std::endl; - Assert(false, - "Due to opset version, the model exporting is aborted, please set " - "a higher opset_version or set auto_upgrade_opset=true."); + P2OLogger() << "Please set the opset_version to " << std::to_string(opset_version) << " or set auto_upgrade_opset=true." << std::endl; + opset_is_legal = false; } } else { if (min_opset > opset_version) { - P2OLogger() << "Opset version will change to " << min_opset << " from " - << opset_version << std::endl; + P2OLogger() << "Opset version will change to " << min_opset << " from " << opset_version << std::endl; opset_version = min_opset; } } + Assert(opset_is_legal, "Due to opset version, the model exporting is aborted."); _helper.SetOpsetVersion(opset_version); - P2OLogger(verbose) << "Use opset_version = " << _helper.GetOpsetVersion() - << " for ONNX export." << std::endl; + auto opset_import = model->add_opset_import(); + opset_import->set_domain(""); + opset_import->set_version(opset_version); + P2OLogger(verbose) << "Use opset_version = " << _helper.GetOpsetVersion() << " for ONNX export." << std::endl; + + // Set the IR Version of the ONNX model. + auto ir_version = _helper.GetIRVersion(); + model->set_ir_version(ir_version); + ExportParameters(parser.params); ExportInputOutputs(parser.inputs, parser.outputs); - // Only convert blocks 0 now - // because control flow is not supported yet + // Only convert blocks 0 now, because control flow is not supported yet. for (auto i = 0; i < parser.NumOfOps(0); ++i) { auto op = parser.GetOpDesc(0, i); @@ -421,20 +424,10 @@ namespace paddle2onnx ExportOp(parser, &_helper, opset_version, 0, i, verbose); } - // construct a onnx model proto - auto ir_version = _helper.GetIRVersion(); - auto model = std::make_shared(); - model->set_ir_version(ir_version); - auto graph = model->mutable_graph(); graph->set_name("Model from PaddlePaddle."); - auto opset_id = model->add_opset_import(); - opset_id->set_domain(""); - opset_id->set_version(opset_version); - - ProcessGraphDumplicateNames(¶meters, &inputs, &outputs, &_helper.nodes, - &_helper.quantize_info); + ProcessGraphDumplicateNames(¶meters, &inputs, &outputs, &_helper.nodes, &_helper.quantize_info); if (parser.is_quantized_model) { quantize_model_processer.ProcessQuantizeModel( @@ -564,53 +557,47 @@ namespace paddle2onnx { int32_t opset_version = _helper.GetOpsetVersion(); int32_t max_opset = 7; - bool exportable = true; - // Record the number of ops that need to be converted - int converted_op_num = 0; std::set verbose_log; for (auto i = 0; i < parser.NumOfBlocks(); ++i) { for (auto j = 0; j < parser.NumOfOps(i); ++j) { auto op = parser.GetOpDesc(i, j); + + // Skip the input and output nodes. if (op.type() == "feed" || op.type() == "fetch") { continue; } - converted_op_num += 1; - int current_min_opset = 7; + + int current_opset = 7; if (op.type() == "while") { P2OLogger() << "Detected there's control flow 'while' op in your " "model, this requires the minimal opset version of 13." << std::endl; - current_min_opset = 13; + current_opset = 13; } else { auto mapper = MapperHelper::Get()->CreateMapper(op.type(), parser, &_helper, i, j); - current_min_opset = mapper->GetMinOpset(verbose); + current_opset = mapper->GetMinOpset(verbose); delete mapper; } - if (current_min_opset < 0) - { - exportable = false; - P2OLogger(verbose) << "Due to the operator: " << op.type() - << ", this model cannot be exported to ONNX." - << std::endl; - } - else if (current_min_opset > max_opset) + + if (current_opset > max_opset) { - max_opset = current_min_opset; - if (verbose && current_min_opset > opset_version) + max_opset = current_opset; + if (verbose && current_opset > opset_version) { verbose_log.insert("Due to the operator: " + op.type() + ", requires opset_version >= " + - std::to_string(current_min_opset) + "."); + std::to_string(current_opset) + "."); } } } } + if (verbose) { for (auto iter = verbose_log.begin(); iter != verbose_log.end(); ++iter) @@ -618,25 +605,7 @@ namespace paddle2onnx P2OLogger() << *iter << std::endl; } } - - // Here we put some checks to make sure - // paddle2onnx could compatible with - // other version of onnx - int32_t max_support_opset = MAX_ONNX_OPSET_VERSION; - if (exportable && (max_opset > MAX_ONNX_OPSET_VERSION)) - { - exportable = false; - P2OLogger() << "[ERROR] The compiled ONNX version only supports opset 7~" - << MAX_ONNX_OPSET_VERSION - << ", but now this model need as least opset " << max_opset - << ", please compile with higher version of ONNX." << std::endl; - } - if (exportable) - { - return max_opset; - } - - return -1; + return max_opset; } ONNX_NAMESPACE::ModelProto ModelExporter::Optimize( From 81fc93bd0d66ee04e9cc4d3b0ab41509871cf427 Mon Sep 17 00:00:00 2001 From: Zheng-Bicheng Date: Fri, 12 Jul 2024 19:45:48 +0800 Subject: [PATCH 3/6] update export all graph --- paddle2onnx/mapper/exporter.cc | 98 +++++++++++++++++----------------- 1 file changed, 48 insertions(+), 50 deletions(-) diff --git a/paddle2onnx/mapper/exporter.cc b/paddle2onnx/mapper/exporter.cc index a4f042440..8c0c8dbbc 100644 --- a/paddle2onnx/mapper/exporter.cc +++ b/paddle2onnx/mapper/exporter.cc @@ -333,18 +333,12 @@ namespace paddle2onnx std::vector disable_fp16_op_types) { _deploy_backend = deploy_backend; - _helper.SetOpsetVersion(opset_version); _total_ops_num = 0; _current_exported_num = 0; for (auto i = 0; i < parser.NumOfBlocks(); ++i) { _total_ops_num += parser.NumOfOps(i); } - _helper.nodes.reserve(_total_ops_num * 3); - Assert(opset_version <= MAX_ONNX_OPSET_VERSION && opset_version >= 7, - "Paddle2ONNX now only support opset version in range of [7, " + - std::to_string(MAX_ONNX_OPSET_VERSION) + "]."); - _helper.Clear(); inputs.clear(); outputs.clear(); parameters.clear(); @@ -396,7 +390,6 @@ namespace paddle2onnx } } Assert(opset_is_legal, "Due to opset version, the model exporting is aborted."); - _helper.SetOpsetVersion(opset_version); auto opset_import = model->add_opset_import(); opset_import->set_domain(""); opset_import->set_version(opset_version); @@ -410,52 +403,58 @@ namespace paddle2onnx ExportInputOutputs(parser.inputs, parser.outputs); // Only convert blocks 0 now, because control flow is not supported yet. - for (auto i = 0; i < parser.NumOfOps(0); ++i) - { - auto op = parser.GetOpDesc(0, i); - if (op.type() == "feed") + for (auto i = 0; i < parser.NumOfBlocks(); ++i) { + // Init Node Help + _helper.SetOpsetVersion(opset_version); + _helper.nodes.reserve(_total_ops_num * 3); + _helper.Clear(); + + for (auto j = 0; j < parser.NumOfOps(i); ++j) { - continue; + auto op = parser.GetOpDesc(i, j); + if (op.type() == "feed") + { + continue; + } + else if (op.type() == "fetch") + { + continue; + } + ExportOp(parser, &_helper, opset_version, i, j, verbose); } - else if (op.type() == "fetch") + + ProcessGraphDumplicateNames(¶meters, &inputs, &outputs, &_helper.nodes, &_helper.quantize_info); + if (parser.is_quantized_model) { - continue; + quantize_model_processer.ProcessQuantizeModel( + ¶meters, &inputs, &outputs, &_helper.nodes, &_helper, + deploy_backend, parser, calibration_cache); + // Update int8 weights in quantized OP to float32 + UpdateParameters(_helper.updated_params); } - ExportOp(parser, &_helper, opset_version, 0, i, verbose); - } - - auto graph = model->mutable_graph(); - graph->set_name("Model from PaddlePaddle."); - ProcessGraphDumplicateNames(¶meters, &inputs, &outputs, &_helper.nodes, &_helper.quantize_info); - if (parser.is_quantized_model) - { - quantize_model_processer.ProcessQuantizeModel( - ¶meters, &inputs, &outputs, &_helper.nodes, &_helper, - deploy_backend, parser, calibration_cache); - // Update int8 weights in quantized OP to float32 - UpdateParameters(_helper.updated_params); - } - - for (auto &item : parameters) - { - *(graph->add_node()) = *(item.get()); - } - for (auto &item : inputs) - { - *(graph->add_input()) = *(item.get()); - } - for (auto &item : _helper.nodes) - { - *(graph->add_node()) = (*item.get()); - } - for (auto &item : outputs) - { - *(graph->add_output()) = (*item.get()); - } - for (auto &item : _helper.value_infos) - { - *(graph->add_value_info()) = (*item.get()); + auto graph = model->mutable_graph(); + graph->set_name("PaddlePaddle Graph " + std::to_string(i)); + for (auto &item : parameters) + { + *(graph->add_node()) = *(item.get()); + } + for (auto &item : inputs) + { + *(graph->add_input()) = *(item.get()); + } + for (auto &item : _helper.nodes) + { + *(graph->add_node()) = (*item.get()); + } + for (auto &item : outputs) + { + *(graph->add_output()) = (*item.get()); + } + for (auto &item : _helper.value_infos) + { + *(graph->add_value_info()) = (*item.get()); + } } ONNX_NAMESPACE::ModelProto onnx_model; @@ -493,8 +492,7 @@ namespace paddle2onnx } if (external_data_file.size()) { - SaveExternalData(onnx_model.mutable_graph(), external_data_file, - save_external); + SaveExternalData(onnx_model.mutable_graph(), external_data_file, save_external); } // check model if (enable_onnx_checker) From b4a0b94063e1ba2e2da9fa2587db239b16688e80 Mon Sep 17 00:00:00 2001 From: Zheng-Bicheng Date: Fri, 12 Jul 2024 20:05:14 +0800 Subject: [PATCH 4/6] remove unuseful --- paddle2onnx/mapper/exporter.cc | 66 ++++++++++++++-------------------- paddle2onnx/mapper/exporter.h | 6 ++-- 2 files changed, 28 insertions(+), 44 deletions(-) diff --git a/paddle2onnx/mapper/exporter.cc b/paddle2onnx/mapper/exporter.cc index 8c0c8dbbc..565c3992d 100644 --- a/paddle2onnx/mapper/exporter.cc +++ b/paddle2onnx/mapper/exporter.cc @@ -122,33 +122,23 @@ namespace paddle2onnx } } - void ModelExporter::ExportOp(const PaddleParser &parser, OnnxHelper *helper, - int32_t opset_version, int64_t block_id, - int64_t op_id, bool verbose) + void ModelExporter::ExportOp(const PaddleParser &parser, + OnnxHelper *helper, + int32_t opset_version, + int64_t block_id, + int64_t op_id, + bool verbose) { - _current_exported_num += 1; auto op = parser.GetOpDesc(block_id, op_id); -#ifdef PADDLE2ONNX_DEBUG - P2OLogger(true) << "---Converting operator: " << op.type() << " ---" - << std::endl; -#endif if (op.type() == "while") { return ExportLoop(parser, helper, opset_version, block_id, op_id, verbose); } auto mapper = MapperHelper::Get()->CreateMapper(op.type(), parser, helper, block_id, op_id); - mapper->deploy_backend = _deploy_backend; -#ifdef PADDLE2ONNX_DEBUG - P2OLogger(true) << "Mapper Name: " << mapper->Name() << std::endl; -#endif + mapper->deploy_backend = deploy_backend_; mapper->Run(); delete mapper; - -#ifdef PADDLE2ONNX_DEBUG - P2OLogger(true) << "---Converting operator: " << op.type() << " done---" - << std::endl; -#endif } void ModelExporter::ProcessGraphDumplicateNames( @@ -332,13 +322,7 @@ namespace paddle2onnx bool export_fp16_model, std::vector disable_fp16_op_types) { - _deploy_backend = deploy_backend; - _total_ops_num = 0; - _current_exported_num = 0; - for (auto i = 0; i < parser.NumOfBlocks(); ++i) - { - _total_ops_num += parser.NumOfOps(i); - } + deploy_backend_ = deploy_backend; inputs.clear(); outputs.clear(); parameters.clear(); @@ -369,7 +353,8 @@ namespace paddle2onnx // Set the Opset Version of the ONNX model. bool opset_is_legal = true; int32_t min_opset = GetMinOpset(parser, verbose); - if(min_opset < 7 || min_opset >= MAX_ONNX_OPSET_VERSION) { + if (min_opset < 7 || min_opset >= MAX_ONNX_OPSET_VERSION) + { P2OLogger() << "The Opset Version must be between 7 and " << MAX_ONNX_OPSET_VERSION - 1 << std::endl; opset_is_legal = false; } @@ -393,21 +378,22 @@ namespace paddle2onnx auto opset_import = model->add_opset_import(); opset_import->set_domain(""); opset_import->set_version(opset_version); - P2OLogger(verbose) << "Use opset_version = " << _helper.GetOpsetVersion() << " for ONNX export." << std::endl; + P2OLogger(verbose) << "Use opset_version = " << helper_.GetOpsetVersion() << " for ONNX export." << std::endl; // Set the IR Version of the ONNX model. - auto ir_version = _helper.GetIRVersion(); + auto ir_version = helper_.GetIRVersion(); model->set_ir_version(ir_version); ExportParameters(parser.params); ExportInputOutputs(parser.inputs, parser.outputs); // Only convert blocks 0 now, because control flow is not supported yet. - for (auto i = 0; i < parser.NumOfBlocks(); ++i) { + for (auto i = 0; i < parser.NumOfBlocks(); ++i) + { // Init Node Help - _helper.SetOpsetVersion(opset_version); - _helper.nodes.reserve(_total_ops_num * 3); - _helper.Clear(); + helper_.SetOpsetVersion(opset_version); + helper_.nodes.reserve(parser.NumOfOps(i) * 3); + helper_.Clear(); for (auto j = 0; j < parser.NumOfOps(i); ++j) { @@ -420,17 +406,17 @@ namespace paddle2onnx { continue; } - ExportOp(parser, &_helper, opset_version, i, j, verbose); + ExportOp(parser, &helper_, opset_version, i, j, verbose); } - ProcessGraphDumplicateNames(¶meters, &inputs, &outputs, &_helper.nodes, &_helper.quantize_info); + ProcessGraphDumplicateNames(¶meters, &inputs, &outputs, &helper_.nodes, &helper_.quantize_info); if (parser.is_quantized_model) { quantize_model_processer.ProcessQuantizeModel( - ¶meters, &inputs, &outputs, &_helper.nodes, &_helper, + ¶meters, &inputs, &outputs, &helper_.nodes, &helper_, deploy_backend, parser, calibration_cache); // Update int8 weights in quantized OP to float32 - UpdateParameters(_helper.updated_params); + UpdateParameters(helper_.updated_params); } auto graph = model->mutable_graph(); @@ -443,7 +429,7 @@ namespace paddle2onnx { *(graph->add_input()) = *(item.get()); } - for (auto &item : _helper.nodes) + for (auto &item : helper_.nodes) { *(graph->add_node()) = (*item.get()); } @@ -451,7 +437,7 @@ namespace paddle2onnx { *(graph->add_output()) = (*item.get()); } - for (auto &item : _helper.value_infos) + for (auto &item : helper_.value_infos) { *(graph->add_value_info()) = (*item.get()); } @@ -539,7 +525,7 @@ namespace paddle2onnx else if (!enable_experimental_op) { auto mapper = MapperHelper::Get()->CreateMapper(op.type(), parser, - &_helper, i, j); + &helper_, i, j); if (mapper->IsExperimentalOp()) { unsupported_ops->insert(op.type()); @@ -553,7 +539,7 @@ namespace paddle2onnx int32_t ModelExporter::GetMinOpset(const PaddleParser &parser, bool verbose) { - int32_t opset_version = _helper.GetOpsetVersion(); + int32_t opset_version = helper_.GetOpsetVersion(); int32_t max_opset = 7; std::set verbose_log; for (auto i = 0; i < parser.NumOfBlocks(); ++i) @@ -578,7 +564,7 @@ namespace paddle2onnx } else { - auto mapper = MapperHelper::Get()->CreateMapper(op.type(), parser, &_helper, i, j); + auto mapper = MapperHelper::Get()->CreateMapper(op.type(), parser, &`, i, j); current_opset = mapper->GetMinOpset(verbose); delete mapper; } diff --git a/paddle2onnx/mapper/exporter.h b/paddle2onnx/mapper/exporter.h index 775c61306..7e7da1ce5 100644 --- a/paddle2onnx/mapper/exporter.h +++ b/paddle2onnx/mapper/exporter.h @@ -48,10 +48,8 @@ namespace paddle2onnx std::vector> inputs; std::vector> outputs; // The _deploy_backend will pass to Mapper to influence the conversion - std::string _deploy_backend = "onnxruntime"; - OnnxHelper _helper; - int32_t _total_ops_num = 0; - int32_t _current_exported_num = 0; + std::string deploy_backend_ = "onnxruntime"; + OnnxHelper helper_; void ExportParameters(const std::map ¶ms, bool use_initializer = false); From b998d7acee2f8b4d1f0aaa2d62b31e1c6eee2515 Mon Sep 17 00:00:00 2001 From: Zheng-Bicheng Date: Fri, 12 Jul 2024 20:53:33 +0800 Subject: [PATCH 5/6] update code style --- paddle2onnx/mapper/exporter.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paddle2onnx/mapper/exporter.cc b/paddle2onnx/mapper/exporter.cc index 565c3992d..4c2b38903 100644 --- a/paddle2onnx/mapper/exporter.cc +++ b/paddle2onnx/mapper/exporter.cc @@ -564,7 +564,7 @@ namespace paddle2onnx } else { - auto mapper = MapperHelper::Get()->CreateMapper(op.type(), parser, &`, i, j); + auto mapper = MapperHelper::Get()->CreateMapper(op.type(), parser, &helper_, i, j); current_opset = mapper->GetMinOpset(verbose); delete mapper; } From 33ccbf803a400de8d21facbb43f351a312926c10 Mon Sep 17 00:00:00 2001 From: Zheng-Bicheng Date: Fri, 12 Jul 2024 21:00:23 +0800 Subject: [PATCH 6/6] update set opset version --- paddle2onnx/mapper/exporter.cc | 49 ++++++++++++++++++++++-- paddle2onnx/mapper/exporter.h | 63 ++++++++++++++++--------------- paddle2onnx/mapper/onnx_helper.cc | 41 -------------------- paddle2onnx/mapper/onnx_helper.h | 2 - 4 files changed, 77 insertions(+), 78 deletions(-) diff --git a/paddle2onnx/mapper/exporter.cc b/paddle2onnx/mapper/exporter.cc index 4c2b38903..04e780d42 100644 --- a/paddle2onnx/mapper/exporter.cc +++ b/paddle2onnx/mapper/exporter.cc @@ -308,6 +308,46 @@ namespace paddle2onnx << std::endl; } + ONNX_NAMESPACE::Version ModelExporter::GetIRVersion() const { + int ir_version = 0; + switch (opset_version_) { + case 7: + case 8: + ir_version = 3; + break; + case 9: + ir_version = 4; + break; + case 10: + ir_version = 5; + break; + case 11: + ir_version = 6; + break; + case 12: + case 13: + case 14: + ir_version = 7; + break; + case 15: + case 16: + case 17: + case 18: + ir_version = 8; + break; + case 19: + case 20: + ir_version = 9; + break; + case 21: + ir_version = 10; + break; + default: + Assert(false, "Opset version must be 7-20"); + } + return static_cast(ir_version); + } + std::string ModelExporter::Run(const PaddleParser &parser, int opset_version, bool auto_upgrade_opset, @@ -375,14 +415,15 @@ namespace paddle2onnx } } Assert(opset_is_legal, "Due to opset version, the model exporting is aborted."); + + opset_version_ = opset_version; auto opset_import = model->add_opset_import(); opset_import->set_domain(""); - opset_import->set_version(opset_version); - P2OLogger(verbose) << "Use opset_version = " << helper_.GetOpsetVersion() << " for ONNX export." << std::endl; + opset_import->set_version(opset_version_); + P2OLogger(verbose) << "Use opset_version = " << opset_version_ << " for ONNX export." << std::endl; // Set the IR Version of the ONNX model. - auto ir_version = helper_.GetIRVersion(); - model->set_ir_version(ir_version); + model->set_ir_version(GetIRVersion()); ExportParameters(parser.params); ExportInputOutputs(parser.inputs, parser.outputs); diff --git a/paddle2onnx/mapper/exporter.h b/paddle2onnx/mapper/exporter.h index 7e7da1ce5..44104f07f 100644 --- a/paddle2onnx/mapper/exporter.h +++ b/paddle2onnx/mapper/exporter.h @@ -40,38 +40,8 @@ inline std::string GetFilenameFromPath(const std::string &path) namespace paddle2onnx { - struct ModelExporter { - private: - std::vector> parameters; - std::vector> inputs; - std::vector> outputs; - // The _deploy_backend will pass to Mapper to influence the conversion - std::string deploy_backend_ = "onnxruntime"; - OnnxHelper helper_; - - void ExportParameters(const std::map ¶ms, - bool use_initializer = false); - - // Update constant node in parameters. When process quantize model, the weight - // dtype may be int8, it should be convet to float32 and use this function to - // update converted params. - void UpdateParameters(const std::map ¶ms); - void ExportInputOutputs(const std::vector &input_infos, - const std::vector &output_infos); - void ExportOp(const PaddleParser &parser, OnnxHelper *helper, - int32_t opset_version, int64_t block_id, int64_t op_id, - bool verbose); - bool IsLoopSupported(const PaddleParser &parser, const int64_t &block_id, - const int64_t &op_id); - void ExportLoop(const PaddleParser &parser, OnnxHelper *helper, - int32_t opset_version, int64_t block_id, int64_t op_id, - bool verbose); - void CovertCustomOps(const PaddleParser &parser, OnnxHelper *helper, - int64_t block_id, int64_t op_id); - ONNX_NAMESPACE::ModelProto Optimize(const ONNX_NAMESPACE::ModelProto &model); - public: QuantizeModelProcessor quantize_model_processer; // Get a proper opset version in range of [7, 16] @@ -119,6 +89,37 @@ namespace paddle2onnx bool *save_external = nullptr, bool export_fp16_model = false, std::vector disable_fp16_op_types = {}); - }; + private: + std::vector> parameters; + std::vector> inputs; + std::vector> outputs; + // The _deploy_backend will pass to Mapper to influence the conversion + std::string deploy_backend_ = "onnxruntime"; + OnnxHelper helper_; + int32_t opset_version_ = 7; + + void ExportParameters(const std::map ¶ms, + bool use_initializer = false); + + // Update constant node in parameters. When process quantize model, the weight + // dtype may be int8, it should be convet to float32 and use this function to + // update converted params. + void UpdateParameters(const std::map ¶ms); + void ExportInputOutputs(const std::vector &input_infos, + const std::vector &output_infos); + void ExportOp(const PaddleParser &parser, OnnxHelper *helper, + int32_t opset_version, int64_t block_id, int64_t op_id, + bool verbose); + bool IsLoopSupported(const PaddleParser &parser, const int64_t &block_id, + const int64_t &op_id); + void ExportLoop(const PaddleParser &parser, OnnxHelper *helper, + int32_t opset_version, int64_t block_id, int64_t op_id, + bool verbose); + void CovertCustomOps(const PaddleParser &parser, OnnxHelper *helper, + int64_t block_id, int64_t op_id); + ONNX_NAMESPACE::ModelProto Optimize(const ONNX_NAMESPACE::ModelProto &model); + + ONNX_NAMESPACE::Version GetIRVersion() const; + }; } // namespace paddle2onnx diff --git a/paddle2onnx/mapper/onnx_helper.cc b/paddle2onnx/mapper/onnx_helper.cc index d0833363d..419fa1f4b 100755 --- a/paddle2onnx/mapper/onnx_helper.cc +++ b/paddle2onnx/mapper/onnx_helper.cc @@ -545,45 +545,4 @@ std::vector OnnxHelper::DtypeAlignment( } return casted_node; } - - -ONNX_NAMESPACE::Version OnnxHelper::GetIRVersion() const { - int ir_version = 0; - switch (opset_version) { - case 7: - case 8: - ir_version = 3; - break; - case 9: - ir_version = 4; - break; - case 10: - ir_version = 5; - break; - case 11: - ir_version = 6; - break; - case 12: - case 13: - case 14: - ir_version = 7; - break; - case 15: - case 16: - case 17: - case 18: - ir_version = 8; - break; - case 19: - case 20: - ir_version = 9; - break; - case 21: - ir_version = 10; - break; - default: - Assert(false, "Opset version must be 7-20"); - } - return static_cast(ir_version); -} } // namespace paddle2onnx diff --git a/paddle2onnx/mapper/onnx_helper.h b/paddle2onnx/mapper/onnx_helper.h index 4696bca5b..e59aaba3a 100644 --- a/paddle2onnx/mapper/onnx_helper.h +++ b/paddle2onnx/mapper/onnx_helper.h @@ -215,8 +215,6 @@ class OnnxHelper { std::string Assign(const ONNX_NAMESPACE::TensorProto_DataType &dtype, const std::vector &shape, const std::vector &value); - - ONNX_NAMESPACE::Version GetIRVersion() const; };