Browse Source

Description:aclgrphParse IR interface

Team:HISI_SW
Feature or Bugfix:Feature
pull/63/head
l00444296 5 years ago
parent
commit
300d79f79d
6 changed files with 821 additions and 59 deletions
  1. +4
    -0
      inc/external/parser/caffe_parser.h
  2. +3
    -0
      inc/external/parser/tensorflow_parser.h
  3. +57
    -1
      parser/caffe/caffe_parser.cc
  4. +679
    -55
      parser/common/acl_graph_parser_util.cc
  5. +30
    -2
      parser/common/acl_graph_parser_util.h
  6. +48
    -1
      parser/tensorflow/tensorflow_parser.cc

+ 4
- 0
inc/external/parser/caffe_parser.h View File

@@ -27,6 +27,10 @@

namespace ge {
graphStatus aclgrphParseCaffe(const char *model_file, const char *weights_file, ge::Graph &graph);

graphStatus aclgrphParseCaffe(const char *model_file, const char *weights_file,
const std::map<std::string, std::string> &parser_params,
ge::Graph &graph);
} // namespace ge

#endif // INC_EXTERNAL_ACL_GRAPH_CAFFE_H_

+ 3
- 0
inc/external/parser/tensorflow_parser.h View File

@@ -28,6 +28,9 @@

namespace ge {
graphStatus aclgrphParseTensorFlow(const char *model_file, ge::Graph &graph);
graphStatus aclgrphParseTensorFlow(const char *model_file,
const std::map<std::string, std::string> &parser_params,
ge::Graph &graph);
} // namespace ge

#endif // INC_EXTERNAL_ACL_PARSER_TENSORFLOW_H_

+ 57
- 1
parser/caffe/caffe_parser.cc View File

@@ -107,12 +107,68 @@ graphStatus aclgrphParseCaffe(const char *model_file, const char *weights_file,
return ret;
}
GELOGI("Weights parse success. graph: %s", graph.GetName().c_str());
if (acl_graph_parse_util.SetDefaultOutputNode(graph) != ge::SUCCESS) {
std::map<string, string> &parser_params;
if (acl_graph_parse_util.SetOutputNodeInfo(graph, parser_params) != ge::SUCCESS) {
GELOGE(ret, "Set graph %s default output node failed.", graph.GetName().c_str());
return ge::FAILED;
}
return ge::SUCCESS;
}

graphStatus aclgrphParseCaffe(const char *model_file, const char *weights_file,
const std::map<std::string, std::string> &parser_params,
ge::Graph &graph) {
GE_CHECK_NOTNULL(model_file);
GetParserContext().type = domi::CAFFE;
std::map<string, string> options;
options.insert(std::pair<string, string>(string(ge::FRAMEWORK_TYPE), to_string(ge::CAFFE)));

// load custom plugin so and proto
AclGrphParseUtil acl_graph_parse_util;
(void)acl_graph_parse_util.AclParserInitialize(options);

string output_name;
if (acl_graph_parse_util.ParseParamsBeforeGraph(parser_params, output_name) != ge::SUCCESS) {
GELOGE(ge::FAILED, "Parser params before graph failed.");
return ge::FAILED;
}
// Create an empty computegraph
string graph_name = output_name.empty() ? "tmpGraph", output_name;
ge::ComputeGraphPtr compute_graph = ge::parser::MakeShared<ge::ComputeGraph>(graph_name);
GE_CHECK_NOTNULL(compute_graph);

graph = ge::GraphUtils::CreateGraphFromComputeGraph(compute_graph);
auto model_parser = domi::ModelParserFactory::Instance()->CreateModelParser(domi::CAFFE);
GE_CHECK_NOTNULL(model_parser);

// parse caffe model_file and weights_file to GE graph
ge::graphStatus ret = model_parser->Parse(model_file, graph);
if (ret != ge::SUCCESS) {
GELOGE(ret, "Parser graph %s failed.", graph.GetName().c_str());
return ge::FAILED;
}
GELOGI("Parser graph %s success.", graph.GetName().c_str());

if (acl_graph_parse_util.ParseParamsAfterGraph(graph, parser_params) != ge::SUCCESS) {
GELOGE(ge::FAILED, "Parser params after graph failed.");
return ge::FAILED;
}

auto weights_parser = domi::WeightsParserFactory::Instance()->CreateWeightsParser(domi::CAFFE);
ret = weights_parser->Parse(weights_file, graph);
if (ret != ge::SUCCESS) {
GELOGE(ret, "Weights parse failed. graph: %s", graph.GetName().c_str());
return ret;
}
GELOGI("Weights parse success. graph: %s", graph.GetName().c_str());

if (acl_graph_parse_util.SetOutputNodeInfo(graph, parser_params) != ge::SUCCESS) {
GELOGE(ge::FAILED, "Set graph %s default output node failed.", graph.GetName().c_str());
return ge::FAILED;
}
GELOGI("AclgrphParse graph %s success.", graph.GetName().c_str());
return ge::SUCCESS;
}
} // namespace ge




+ 679
- 55
parser/common/acl_graph_parser_util.cc View File

@@ -25,6 +25,7 @@
#include "common/string_util.h"
#include "common/debug/log.h"
#include "common/op/ge_op_utils.h"
#include "common/properties_manager.h"
#include "ge/ge_api_types.h"
#include "graph/opsproto_manager.h"
#include "omg/parser/parser_inner_ctx.h"
@@ -42,6 +43,28 @@ using google::protobuf::io::ZeroCopyInputStream;
using namespace ge::parser;

namespace {
static std::map<std::string, domiTensorFormat_t> kInputFormatStrToGeformat = {
{"ND", domi::DOMI_TENSOR_ND},
{"NCHW", domi::DOMI_TENSOR_NCHW},
{"NHWC", domi::DOMI_TENSOR_NHWC},
{"CHWN", domi::DOMI_TENSOR_CHWN},
{"NC1HWC0", domi::DOMI_TENSOR_NC1HWC0},
{"NHWC1C0", domi::DOMI_TENSOR_NHWC1C0},
{"NCDHW", domi::DOMI_TENSOR_NCDHW},
{"NDHWC", domi::DOMI_TENSOR_NDHWC}
};
static char *const kIsOutputAdjustHwLayoutKey = "is_output_adjust_hw_layout";
// datatype/formats from user to GE, Unified to util interface file later
const std::map<std::string, ge::DataType> kOutputTypeSupportDatatype = {
{"FP32", ge::DT_FLOAT}, {"FP16", ge::DT_FLOAT16}, {"UINT8", ge::DT_UINT8}};
const char *const kOutputTypeSupport = "only support FP32, FP16, UINT8";
const char *const kInputShapeSample1 = "\"input_name1:n1,c1,h1,w1\"";
const char *const kInputShapeSample2 = "\"input_name1:1,3,224,224\"";
const char *const kSplitError1 = "size not equal to 2 split by \":\"";
const char *const kEmptyError = "can not be empty";
const char *const kFloatNumError = "exist float number";
const char *const kDigitError = "is not digit";

/// The maximum length of the file.
/// Based on the security coding specification and the current actual (protobuf) model size, it is determined as 2G-1
const int kMaxFileSizeLimit = INT_MAX;
@@ -92,78 +115,90 @@ static void GetOpsProtoPath(string &opsproto_path) {
path_base = path_base.substr(0, path_base.rfind('/') + 1);
opsproto_path = (path_base + "ops/op_proto/custom/" + ":") + (path_base + "ops/op_proto/built-in/");
}
} // namespace

namespace ge {
domi::Status AclGrphParseUtil::GetOutputLeaf(NodePtr node,
std::vector<std::pair<ge::NodePtr, int32_t>> &output_nodes_info) {
ge::OpDescPtr tmpDescPtr = node->GetOpDesc();
if (tmpDescPtr == nullptr) {
GELOGE(domi::FAILED, "Get outnode op desc fail.");
return domi::FAILED;
}
size_t size = tmpDescPtr->GetOutputsSize();
if (node->GetType() != NETOUTPUT) {
for (size_t index = 0; index < size; ++index) {
output_nodes_info.push_back(std::make_pair(node, index));
}
static void GetAclParams(const std::map<string, string> &parser_params,
const string &key, string &value) {
auto iter = parser_params.find(key);
if (iter != parser_params.end()) {
value = iter->second;
} else {
const auto in_anchors = node->GetAllInDataAnchors();
for (auto in_anchor : in_anchors) {
auto out_anchor = in_anchor->GetPeerOutAnchor();
if (out_anchor == nullptr) {
GELOGE(domi::FAILED, "Get leaf node op desc fail.");
return domi::FAILED;
}
auto out_node = out_anchor->GetOwnerNode();
output_nodes_info.push_back(std::make_pair(out_node, out_anchor->GetIdx()));
}
value = "";
}
return SUCCESS;
}

void AclGrphParseUtil::GetOutputNodesNameAndIndex(std::vector<std::pair<ge::NodePtr, int32_t>> &output_nodes_info,
std::vector<std::string> &output_nodes_name) {
output_nodes_name.clear();
if (ge::GetParserContext().out_top_names.empty()) {
// tf process, no top name.
for (const auto output_node_info : output_nodes_info) {
std::string node_name = output_node_info.first->GetName();
int32_t index = output_node_info.second;
output_nodes_name.push_back(node_name + ":" + std::to_string(index));
static bool CheckDigitStr(std::string &str) {
for (char c : str) {
if (!isdigit(c)) {
GELOGE(domi::FAILED, "value[%s] is not positive integer", str.c_str());
return false;
}
return;
}
// caffe process reserved place;
return true;
}
} // namespace

domi::Status AclGrphParseUtil::SetDefaultOutputNode(ge::Graph &graph) {
ge::ComputeGraphPtr compute_graph = ge::GraphUtils::GetComputeGraph(graph);
if (compute_graph == nullptr) {
GELOGE(FAILED, "compute_graph is nullptr.");
return FAILED;
namespace ge {
static bool CheckInputTrueOrFalse(const std::string &s, const std::string &atc_param) {
if ((s == "true") || (s == "false")) {
return true;
} else {
ErrorManager::GetInstance().ATCReportErrMessage("E10005", {"parameter", "value"}, {atc_param, s});
GELOGE(PARAM_INVALID, "Input parameter[--%s]'s value[%s] must be true or false.", atc_param.c_str(), s.c_str());
return false;
}
}

std::vector<std::pair<ge::NodePtr, int32_t>> output_nodes_info;
std::vector<std::string> output_nodes_name;
static domi::Status CheckOutPutDataTypeSupport(const std::string &output_type) {
auto it = kOutputTypeSupportDatatype.find(output_type);
if (it == kOutputTypeSupportDatatype.end()) {
ErrorManager::GetInstance().ATCReportErrMessage("E10001", {"parameter", "value", "reason"},
{"--output_type", output_type, kOutputTypeSupport});
GELOGE(PARAM_INVALID, "Invalid value for --output_type[%s], %s.", output_type.c_str(), kOutputTypeSupport);
return domi::PARAM_INVALID;
}
return domi::SUCCESS;
}

for (ge::NodePtr node : compute_graph->GetDirectNode()) {
if (!node->GetInAllNodes().empty() && node->GetOutAllNodes().empty()) {
Status ret = AclGrphParseUtil::GetOutputLeaf(node, output_nodes_info);
if (ret != SUCCESS) {
GELOGE(FAILED, "find leaf fail.");
return FAILED;
}
static domi::Status StringToInt(std::string &str, int32_t &value) {
try {
if (!CheckDigitStr(str)) {
GELOGE(PARAM_INVALID, "Invalid of digit string: %s ", str.c_str());
ErrorManager::GetInstance().ATCReportErrMessage("E10001", {"parameter", "value", "reason"},
{"--output_type", str, "is not positive integer"});
return PARAM_INVALID;
}
value = stoi(str);
} catch (std::invalid_argument &) {
GELOGE(PARAM_INVALID, "Invalid of digit string: %s, catch invalid_argument.", str.c_str());
ErrorManager::GetInstance().ATCReportErrMessage("E10014", {"parameter", "value"}, {"--output_type", str});
return PARAM_INVALID;
} catch (std::out_of_range &) {
GELOGE(PARAM_INVALID, "Invalid of digit string: %s, catch out_of_range.", str.c_str());
ErrorManager::GetInstance().ATCReportErrMessage("E10013", {"parameter", "value"}, {"--output_type", str});
return PARAM_INVALID;
}

AclGrphParseUtil::GetOutputNodesNameAndIndex(output_nodes_info, output_nodes_name);
compute_graph->SetGraphOutNodesInfo(output_nodes_info);
ge::GetParserContext().net_out_nodes = output_nodes_name;
GELOGI("Set graph %s default output node success.", graph.GetName().c_str());
return SUCCESS;
}

domi::Status VerifyOutputTypeAndOutNodes(std::vector<std::string> &out_type_vec) {
std::vector<std::pair<std::string, int32_t>> user_out_nodes = domi::GetContext().user_out_nodes;
std::set<std::string> out_nodes_info;
for (uint32_t i = 0; i < user_out_nodes.size(); ++i) {
// out_nodes set should include output_type and output_format
std::string tmp = user_out_nodes[i].first + ":" + to_string(user_out_nodes[i].second);
out_nodes_info.emplace(tmp);
}
for (uint32_t i = 0; i < out_type_vec.size(); ++i) {
if (out_nodes_info.find(out_type_vec[i]) == out_nodes_info.end()) {
ErrorManager::GetInstance().ATCReportErrMessage("E10001", {"parameter", "value", "reason"},
{"--output_type", out_type_vec[i], kOutputTypeError});
GELOGE(domi::FAILED, "Invalid value for --output_type[%s], %s.", out_type_vec[i].c_str(), kOutputTypeError);
return domi::FAILED;
}
}
return domi::SUCCESS;
}

domi::Status AclGrphParseUtil::LoadOpsProtoLib() {
string opsproto_path;
GetOpsProtoPath(opsproto_path);
@@ -239,6 +274,595 @@ domi::Status AclGrphParseUtil::AclParserInitialize(const std::map<std::string, s
GELOGT(TRACE_STOP, "AclParserInitialize finished");
return SUCCESS;
}

domi::Status AclGrphParseUtil::ParseAclFormat(const string &input_format) {
ge::GetParserContext().format = domi::DOMI_TENSOR_ND;
if (!input_format.empty()) {
auto iter = kInputFormatStrToGeformat.find(input_format);
if (iter != kInputFormatStrToGeformat.end()) {
ge::GetParserContext().format = iter->second;
} else {
GELOGE(PARAM_INVALID, "Input format %s not support , expect ND/NCHW/NHWC/CHWN/NC1HWC0/NHWC1C0.",
input_format.c_str());
return PARAM_INVALID;
}
}
return SUCCESS;
}

bool AclGrphParseUtil::ParseInputShape(const string &input_shape,
unordered_map<string, vector<int64_t>> &shape_map,
vector<pair<string, vector<int64_t>>> &user_shape_map,
bool is_dynamic_input) {
vector<string> shape_vec = StringUtils::Split(input_shape, ';');
const int DEFAULT_SHAPE_PAIR_SIZE = 2;
for (const auto &shape : shape_vec) {
vector<string> shape_pair_vec = SplitInputShape(shape);
if (shape_pair_vec.size() != DEFAULT_SHAPE_PAIR_SIZE) {
ErrorManager::GetInstance().ATCReportErrMessage("E10002", {"shape", "reason", "sample"},
{shape, kSplitError1, kInputShapeSample1});
GELOGW("Parse input parameter [--input_shape]'s shape[%s] failed, reason: %s, correct sample is %s.",
shape.c_str(), kSplitError1, kInputShapeSample1);
return false;
}
if (shape_pair_vec[1].empty()) {
ErrorManager::GetInstance().ATCReportErrMessage("E10002", {"shape", "reason", "sample"},
{shape, kEmptyError, kInputShapeSample1});
GELOGW("Parse input parameter [--input_shape]'s shape[%s] failed, reason: %s, correct sample is %s.",
shape.c_str(), kEmptyError, kInputShapeSample1);
return false;
}

vector<string> shape_value_strs = StringUtils::Split(shape_pair_vec[1], ',');
vector<int64_t> shape_values;
for (auto &shape_value_str : shape_value_strs) {
// stoul: The method may throw an exception: invalid_argument/out_of_range
if (std::string::npos != shape_value_str.find('.')) {
ErrorManager::GetInstance().ATCReportErrMessage("E10002", {"shape", "reason", "sample"},
{shape, kFloatNumError, kInputShapeSample2});
GELOGW("Parse input parameter [--input_shape]'s shape[%s] failed, reason: %s, correct sample is %s.",
shape.c_str(), kFloatNumError, kInputShapeSample2);
return false;
}

long left_result = 0;
try {
left_result = stol(StringUtils::Trim(shape_value_str));
if (!shape_value_str.empty() && (shape_value_str.front() == '-')) {
// The value maybe dynamic shape [-1], need substr it and verify isdigit.
shape_value_str = shape_value_str.substr(1);
}
for (char c : shape_value_str) {
if (!isdigit(c)) {
ErrorManager::GetInstance().ATCReportErrMessage("E10002", {"shape", "reason", "sample"},
{shape, kDigitError, kInputShapeSample2});
GELOGE(PARAM_INVALID, "--input_shape's shape value[%s] is not digit", shape_value_str.c_str());
return false;
}
}
} catch (const std::out_of_range &) {
ErrorManager::GetInstance().ATCReportErrMessage("E10013", {"parameter", "value"},
{"--input_shape", shape_value_str});
GELOGW("Input parameter[--input_shape]’s value[%s] cause out of range execption!", shape_value_str.c_str());
return false;
} catch (const std::invalid_argument &) {
ErrorManager::GetInstance().ATCReportErrMessage("E10014", {"parameter", "value"},
{"--input_shape", shape_value_str});
GELOGW("Input parameter[--input_shape]’s value[%s] cause invalid argument!", shape_value_str.c_str());
return false;
} catch (...) {
ErrorManager::GetInstance().ATCReportErrMessage("E10015", {"parameter", "value"},
{"--input_shape", shape_value_str});
GELOGW("Input parameter[--input_shape]’s value[%s] cause unkown execption!", shape_value_str.c_str());
return false;
}
int64_t result = left_result;
// - 1 is not currently supported
if (!is_dynamic_input && result <= 0) {
ErrorManager::GetInstance().ATCReportErrMessage("E10011", {"shape", "result"}, {shape, std::to_string(result)});
GELOGW(
"Input parameter[--input_shape]’s shape value[%s] is invalid, "
"expect positive integer, but value is %ld.",
shape.c_str(), result);
return false;
}
shape_values.push_back(result);
}

shape_map.emplace(make_pair(StringUtils::Trim(shape_pair_vec[0]), shape_values));
user_shape_map.push_back(make_pair(StringUtils::Trim(shape_pair_vec[0]), shape_values));
}

return true;
}

//Parse user input shape info
domi::Status AclGrphParseUtil::ParseAclShape(const string &input_shape, bool is_dynamic_input) {
ge::GetParserContext().input_dims.clear();
ge::GetParserContext().user_input_dims.clear();
ge::GetParserContext().is_dynamic_input = is_dynamic_input;

if (input_shape.empty()) {
return SUCCESS;
}

unordered_map<string, vector<int64_t>> &shape_map = ge::GetParserContext().input_dims;
if (!ParseInputShape(input_shape, ge::GetParserContext().input_dims,
ge::GetParserContext().user_input_dims, is_dynamic_input) || shape_map.empty()) {
GELOGE(PARAM_INVALID, "Failed to parse input shape: %s", input_shape.c_str());
return PARAM_INVALID;
}
return SUCCESS;
}

domi::Status AclGrphParseUtil::ParseAclOutputNodes(const string &out_nodes) {
try {
// parse output node
if (!out_nodes.empty()) {
ge::GetParserContext().out_nodes_map.clear();
ge::GetParserContext().user_out_nodes.clear();
ge::GetParserContext().user_out_nodes_top_vec.clear();

vector<string> nodes_v = StringUtils::Split(out_nodes, ';');
for (const string &node : nodes_v) {
vector<string> key_value_v = StringUtils::Split(node, ':');
if (key_value_v.size() != 2) { // The size must be 2.
if (key_value_v.size() == 1 && ge::GetParserContext().type == domi::CAFFE) {
ge::GetParserContext().user_out_nodes_top_vec.push_back(node);
continue;
}
ErrorManager::GetInstance().ATCReportErrMessage(
"E10001", {"parameter", "value", "reason"},
{"--out_nodes", node, "the correct format is \"node_name1:0;node_name1:1;node_name2:0\""});
GELOGE(PARAM_INVALID,
"The input format of --out_nodes is invalid, the correct format is "
"\"node_name1:0;node_name1:1;node_name2:0\", while the actual input is %s.",
node.c_str());
return PARAM_INVALID;
}
if (!ge::GetParserContext().user_out_nodes_top_vec.empty()) {
ErrorManager::GetInstance().ATCReportErrMessage("E10001", {"parameter", "value", "reason"},
{"--out_nodes", out_nodes, "is not all index or top_name"});
GELOGE(PARAM_INVALID, "This out_nodes str must be all index or top_name, while the actual input is %s", out_nodes.c_str());
return PARAM_INVALID;
}
// stoi: The method may throw an exception: invalid_argument/out_of_range
if (!CheckDigitStr(key_value_v[1])) {
ErrorManager::GetInstance().ATCReportErrMessage("E10001", {"parameter", "value", "reason"},
{"--out_nodes", out_nodes, "is not positive integer"});
GELOGE(PARAM_INVALID, "This str must be digit string, while the actual input is %s", out_nodes.c_str());
return PARAM_INVALID;
}

auto iter = ge::GetParserContext().out_nodes_map.find(key_value_v[0]);
int32_t index = stoi(StringUtils::Trim(key_value_v[1]));
GELOGD("Get output info: node[%s] and index[%ld]", key_value_v[0].c_str(), index);
if (iter != ge::GetParserContext().out_nodes_map.end()) {
iter->second.emplace_back(index);
} else {
std::vector<int32_t> index_v;
index_v.emplace_back(index);
ge::GetParserContext().out_nodes_map.emplace(key_value_v[0], index_v);
}
ge::GetParserContext().user_out_nodes.push_back(std::make_pair(key_value_v[0], index));
}
}
} catch (std::invalid_argument &) {
GELOGE(PARAM_INVALID, "Invalid of out_nodes: %s ", out_nodes.c_str());
ErrorManager::GetInstance().ATCReportErrMessage("E10014", {"parameter", "value"}, {"--out_nodes", out_nodes});
return PARAM_INVALID;
} catch (std::out_of_range &) {
GELOGE(PARAM_INVALID, "Invalid of out_nodes: %s ", out_nodes.c_str());
ErrorManager::GetInstance().ATCReportErrMessage("E10013", {"parameter", "value"}, {"--out_nodes", out_nodes});
return PARAM_INVALID;
}
return SUCCESS;
}

domi::Status AclGrphParseUtil::ParseAclOutputFp16NodesFormat(const string &is_output_fp16) {
if (is_output_fp16.empty()) {
return SUCCESS;
}

vector<domiTensorFormat_t> &output_formats = ge::GetParserContext().output_formats;
output_formats.clear();
vector<string> node_format_vec = StringUtils::Split(is_output_fp16, ',');
for (auto &is_fp16 : node_format_vec) {
StringUtils::Trim(is_fp16);
if (!CheckInputTrueOrFalse(is_fp16, "is_output_adjust_hw_layout")) {
GELOGE(PARAM_INVALID, "Invalid Param, is_output_adjust_hw_layout only support true/false: but is [%s]",
is_output_fp16.c_str());
return PARAM_INVALID;
}
if (is_fp16 == "false") {
output_formats.push_back(DOMI_TENSOR_ND);
} else if (is_fp16 == "true") {
output_formats.push_back(domi::DOMI_TENSOR_NC1HWC0);
}
}
return SUCCESS;
}

domi::Status AclGrphParseUtil::ParseAclOpConf(const char *op_conf) {
// parse configuration item
if (op_conf != nullptr && *op_conf != '\0') {
// divided by ":"
PropertiesManager::Instance().SetPropertyDelimiter(OP_CONF_DELIMITER);
// Parsing the op_conf configuration item file
GE_IF_BOOL_EXEC(!PropertiesManager::Instance().Init(op_conf),
ErrorManager::GetInstance().ATCReportErrMessage("E10003", {"parameter", "value", "reason"},
{"op_name_map", op_conf, "file content error"});
GELOGE(FAILED, "op_name_map init failed!"); return FAILED);
// Return map and put it into ATC global variable
ge::GetParserContext().op_conf_map = PropertiesManager::Instance().GetPropertyMap();
}
}

domi::Status AclGrphParseUtil::ParseAclEnableScope(const string &enable_scope_fusion_passes) {
ge::GetParserContext().enable_scope_fusion_passes.clear();
if (enable_scope_fusion_passes.empty()) {
return SUCCESS;
}
ge::GetParserContext().enable_scope_fusion_passes = enable_scope_fusion_passes;
}

static void AclGrphParseUtil::AddAttrsForInputNodes(const vector<string> &adjust_fp16_format_vec,
const string &fp16_nodes_name, uint32_t index,
OpDescPtr &op_desc) {
if (AttrUtils::SetStr(op_desc, ATTR_ATC_USER_DEFINE_DATATYPE, TypeUtils::DataTypeToSerialString(DT_FLOAT16))) {
if ((index < adjust_fp16_format_vec.size()) && (adjust_fp16_format_vec[index] == "true")) {
GELOGI("This node [%s] should be set NC1HWC0", fp16_nodes_name.c_str());
if (!AttrUtils::SetStr(op_desc, ATTR_ATC_USER_DEFINE_FORMAT, TypeUtils::FormatToSerialString(FORMAT_NC1HWC0))) {
GELOGW("This node [%s] set NC1HWC0 failed", fp16_nodes_name.c_str());
}
}
}
}

domi::Status AclGrphParseUtil::ParseAclInputFp16Nodes(const ComputeGraphPtr &graph,
const string &input_fp16_nodes,
const string &is_input_adjust_hw_layout) {
GE_CHECK_NOTNULL(graph);
vector<string> adjust_fp16_format_vec;
if (!is_input_adjust_hw_layout.empty()) {
adjust_fp16_format_vec = StringUtils::Split(is_input_adjust_hw_layout, ',');
for (auto &s : adjust_fp16_format_vec) {
StringUtils::Trim(s);
if (!CheckInputTrueOrFalse(s, "is_input_adjust_hw_layout")) {
GELOGE(PARAM_INVALID, "Invalid Param, is_input_adjust_hw_layout only support true/false: but is [%s]",
is_input_adjust_hw_layout.c_str());
return PARAM_INVALID;
}
}
}
if (input_fp16_nodes.empty()) {
return SUCCESS;
}
GELOGI("The input_fp16_nodes is set %s", input_fp16_nodes.c_str());
vector<string> input_fp16_nodes_vec = StringUtils::Split(input_fp16_nodes, ';');
for (uint32_t i = 0; i < input_fp16_nodes_vec.size(); ++i) {
ge::NodePtr node = graph->FindNode(input_fp16_nodes_vec[i]);
if (node == nullptr) {
ErrorManager::GetInstance().ATCReportErrMessage("E10016", {"parameter", "opname"},
{"input_fp16_nodes", input_fp16_nodes_vec[i]});
GELOGE(PARAM_INVALID, "Input parameter[--input_fp16_nodes]'s opname[%s] is not exist in model",
input_fp16_nodes_vec[i].c_str());
return PARAM_INVALID;
}
auto op_desc = node->GetOpDesc();
GE_CHECK_NOTNULL(op_desc);
if (op_desc->GetType() != DATA) {
ErrorManager::GetInstance().ATCReportErrMessage("E10017", {"parameter", "opname"},
{"input_fp16_nodes", input_fp16_nodes_vec[i]});
GELOGE(PARAM_INVALID, "Input parameter[--input_fp16_nodes]'s opname[%s] is not a input opname",
input_fp16_nodes_vec[i].c_str());
return PARAM_INVALID;
}
AddAttrsForInputNodes(adjust_fp16_format_vec, input_fp16_nodes_vec[i], i, op_desc);
}
return SUCCESS;
}

domi::Status AclGrphParseUtil::ParseAclWeightCompressConf(const ComputeGraphPtr &graph,
const string &compress_weight_conf) {
GE_CHECK_NOTNULL(graph);
if (compress_weight_conf.empty()) {
return SUCCESS;
}
std::string real_path = RealPath(compress_weight_conf.c_str());
if (real_path.empty()) {
GELOGE(PARAM_INVALID, "Can not get real path for %s.", compress_weight_conf.c_str());
return PARAM_INVALID;
}
std::ifstream ifs(real_path);
if (!ifs.is_open()) {
GELOGE(FAILED, "Open file %s failed", compress_weight_conf.c_str());
return FAILED;
}

std::string compress_nodes;
ifs >> compress_nodes;
ifs.close();
GELOGI("Compress weight of nodes: %s", compress_nodes.c_str());

vector<string> compress_node_vec = StringUtils::Split(compress_nodes, ';');
for (size_t i = 0; i < compress_node_vec.size(); ++i) {
ge::NodePtr node = graph->FindNode(compress_node_vec[i]);
if (node == nullptr) {
GELOGW("node %s is not in graph", compress_node_vec[i].c_str());
continue;
}
auto op_desc = node->GetOpDesc();
GE_CHECK_NOTNULL(op_desc);
if (!ge::AttrUtils::SetBool(op_desc, ge::ATTR_NAME_COMPRESS_WEIGHT, true)) {
GELOGE(domi::FAILED, "node %s SetBool failed.", compress_node_vec[i].c_str());
return domi::FAILED;
}
}
return SUCCESS;
}

domi::Status AclGrphParseUtil::ParseAclOutputType(const std::string &output_type,
std::map<std::string, vector<std::string>> &output_node_dt_map) {
if (output_type.find(':') == std::string::npos) {
GELOGI("output_type is not multiple nodes, means all out nodes");
return CheckOutPutDataTypeSupport(output_type);
}
std::vector<std::string> out_type_vec;
vector<string> nodes_v = StringUtils::Split(output_type, ';');
for (const string &node : nodes_v) {
vector<string> node_index_type_v = StringUtils::Split(node, ':');
if (node_index_type_v.size() != 3) { // The size must be 3.
ErrorManager::GetInstance().ATCReportErrMessage("E10001", {"parameter", "value", "reason"},
{"--output_type", node, kOutputTypeSample});
GELOGE(PARAM_INVALID, "Invalid value for --output_type[%s], %s.", node.c_str(), kOutputTypeSample);
return domi::FAILED;
}
ge::DataType tmp_dt;
std::string node_name = StringUtils::Trim(node_index_type_v[0]);
std::string index_str = StringUtils::Trim(node_index_type_v[1]);
int32_t index;
if (StringToInt(index_str, index) != SUCCESS) {
GELOGE(PARAM_INVALID, "This str must be digit string, while the actual input is %s.", index_str.c_str());
return domi::FAILED;
}
std::string dt_value = StringUtils::Trim(node_index_type_v[2]);
auto it = output_type_str_to_datatype.find(dt_value);
if (it == output_type_str_to_datatype.end()) {
ErrorManager::GetInstance().ATCReportErrMessage("E10001", {"parameter", "value", "reason"},
{"--output_type", dt_value, kOutputTypeSupport});
GELOGE(ge::PARAM_INVALID, "Invalid value for --output_type[%s], %s.", dt_value.c_str(), kOutputTypeSupport);
return domi::FAILED;
} else {
tmp_dt = it->second;
}
out_type_vec.push_back(node_name + ":" + index_str);
std::string index_dt_str = index_str + ":" + TypeUtils::DataTypeToSerialString(tmp_dt);
auto it1 = output_node_dt_map.find(node_name);
if (it1 == output_node_dt_map.end()) {
vector<string> tmp_vec;
tmp_vec.push_back(index_dt_str);
output_node_dt_map.emplace(node_name, tmp_vec);
} else {
it1->second.push_back(index_dt_str);
}
}
return VerifyOutputTypeAndOutNodes(out_type_vec);
}

void AclGrphParseUtil::GetOutputNodesNameAndIndex(std::vector<std::pair<ge::NodePtr, int32_t>> &output_nodes_info,
std::vector<std::string> &output_nodes_name) {
output_nodes_name.clear();
if (domi::GetContext().out_top_names.empty()) {
// tf process, no top name.
for (const auto output_node_info : output_nodes_info) {
std::string node_name = output_node_info.first->GetName();
int32_t index = output_node_info.second;
output_nodes_name.push_back(node_name + ":" + std::to_string(index));
}
return;
}
// caffe process, need add top name after node_name:index
for (size_t i = 0; i < output_nodes_info.size(); ++i) {
std::string node_name = output_nodes_info[i].first->GetName();
int32_t index = output_nodes_info[i].second;
if (i < domi::GetContext().out_top_names.size()) {
output_nodes_name.push_back(node_name + ":" + std::to_string(index) + ":" + domi::GetContext().out_top_names[i]);
} else {
GELOGW("Get top name of node [%s] fail.", node_name.c_str());
output_nodes_name.push_back(node_name + ":" + std::to_string(index));
}
}
}

domi::Status AclGrphParseUtil::GetOutputLeaf(NodePtr node,
std::vector<std::pair<ge::NodePtr, int32_t>> &output_nodes_info) {
ge::OpDescPtr tmpDescPtr = node->GetOpDesc();
if (tmpDescPtr == nullptr) {
GELOGE(domi::FAILED, "Get outnode op desc fail.");
return domi::FAILED;
}
size_t size = tmpDescPtr->GetOutputsSize();
if (node->GetType() != NETOUTPUT) {
for (size_t index = 0; index < size; ++index) {
output_nodes_info.push_back(std::make_pair(node, index));
GELOGD("Get output leaf node:%s.", node->GetName().c_str());
}
} else {
const auto in_anchors = node->GetAllInDataAnchors();
for (auto in_anchor : in_anchors) {
auto out_anchor = in_anchor->GetPeerOutAnchor();
if (out_anchor == nullptr) {
GELOGE(domi::FAILED, "Get leaf node op desc fail.");
return domi::FAILED;
}
auto out_node = out_anchor->GetOwnerNode();
output_nodes_info.push_back(std::make_pair(out_node, out_anchor->GetIdx()));
}
}
return SUCCESS;
}

domi::Status AclGrphParseUtil::GetDefaultOutInfo(ge::ComputeGraphPtr &compute_graph,
std::vector<std::pair<ge::NodePtr, int32_t>> &output_nodes_info) {
std::vector<std::pair<std::string, int32_t>> default_out_nodes = ge::GetParserContext().default_out_nodes;
if (ge::GetParserContext().type == domi::CAFFE && !default_out_nodes.empty()) {
for (uint32_t i = 0; i < default_out_nodes.size(); ++i) {
ge::NodePtr out_node = compute_graph->FindNode(default_out_nodes[i].first);
if (out_node == nullptr) {
ErrorManager::GetInstance().ATCReportErrMessage("E10016", {"parameter", "opname"},
{"out_nodes", default_out_nodes[i].first});
GELOGE(domi::FAILED, "Can not find src node (%s) in graph.", default_out_nodes[i].first.c_str());
return domi::FAILED;
}
output_nodes_info.push_back(std::make_pair(out_node, default_out_nodes[i].second));
GELOGD("Get default output node:%s.", out_node->GetName().c_str());
}
return domi::SUCCESS;
}

for (ge::NodePtr node : compute_graph->GetDirectNode()) {
if (!node->GetInAllNodes().empty() && node->GetOutAllNodes().empty()) {
Status ret = GetOutputLeaf(node, output_nodes_info);
GE_CHK_BOOL_RET_STATUS(ret == SUCCESS, ret, "find leaf fail.");
}
}
return domi::SUCCESS;
}

domi::Status AclGrphParseUtil::SetOutputNodeInfo(ge::Graph &graph,
const std::map<std::string, std::string> &parser_params) {
ge::ComputeGraphPtr compute_graph = ge::GraphUtils::GetComputeGraph(graph);
GE_CHECK_NOTNULL(compute_graph);

string output_type;
GetAclParams(parser_params, "output_type", output_type);

std::vector<std::pair<std::string, int32_t>> user_out_nodes = ge::GetParserContext().user_out_nodes;
std::vector<domiTensorFormat_t> output_formats = ge::GetParserContext().output_formats;
std::vector<std::pair<ge::NodePtr, int32_t>> output_nodes_info;
std::vector<std::string> output_nodes_name;
std::map<std::string, vector<std::string>> output_node_dt_map;
if (!output_type.empty()) {
if (ParseAclOutputType(output_type, output_node_dt_map) != SUCCESS) {
GELOGE(domi::FAILED, "Parse output_type failed.");
return domi::FAILED;
}
}

// User declared outputs
for (uint32_t i = 0; i < user_out_nodes.size(); ++i) {
ge::NodePtr out_node = compute_graph->FindNode(user_out_nodes[i].first);
if (out_node == nullptr) {
ErrorManager::GetInstance().ATCReportErrMessage("E10016", {"parameter", "opname"},
{"out_nodes", user_out_nodes[i].first});
GELOGE(domi::FAILED, "Can not find src node (%s) in graph.", user_out_nodes[i].first.c_str());
return domi::FAILED;
}
auto op_desc = out_node->GetOpDesc();
GE_CHECK_NOTNULL(op_desc);
if (CheckOutNode(op_desc, user_out_nodes[i].second) != SUCCESS) {
GELOGE(domi::FAILED, "Check out node (%s) fail.", user_out_nodes[i].first.c_str());
return domi::FAILED;
}
if (i < output_formats.size()) {
if (output_formats[i] == domi::DOMI_TENSOR_NC1HWC0) {
GELOGI("The output node [%s] should be set NC1HWC0", user_out_nodes[i].first.c_str());
vector<string> output_fp16_5hd_vec;
(void)ge::AttrUtils::GetListStr(op_desc, "_user_defined_output_fp16_5hd", output_fp16_5hd_vec);
output_fp16_5hd_vec.push_back(std::to_string(user_out_nodes[i].second) + ":" + "NC1HWC0");
(void)ge::AttrUtils::SetListStr(op_desc, "_user_defined_output_fp16_5hd", output_fp16_5hd_vec);
}
}
auto it = output_node_dt_map.find(user_out_nodes[i].first);
if (it != output_node_dt_map.end()) {
GELOGI("The output node [%s] need to be set output_type", user_out_nodes[i].first.c_str());
(void)ge::AttrUtils::SetListStr(op_desc, "_user_defined_output_data_type", it->second);
}
output_nodes_info.push_back(std::make_pair(out_node, user_out_nodes[i].second));
}
// default output node (leaf)
if (user_out_nodes.empty()) {
if (GetDefaultOutInfo(compute_graph, output_nodes_info) != SUCCESS) {
GELOGE(domi::FAILED, "Get default output info failed.");
return domi::FAILED;
}
}
GetOutputNodesNameAndIndex(output_nodes_info, output_nodes_name);
compute_graph->SetGraphOutNodesInfo(output_nodes_info);
ge::GetParserContext().net_out_nodes = output_nodes_name;
GELOGI("Set graph %s output node success.", graph.GetName().c_str());
return domi::SUCCESS;
}

domi::Status AclGrphParseUtil::ParseParamsBeforeGraph(const std::map<std::string, std::string> &parser_params,
string &graph_name) {
GELOGI("Parse graph user options start.");
// support paragrams: input_format, is_dynamic_input, input_shape, out_nodes
// is_output_adjust_hw_layout, output, op_name_map, enable_scope_fusion_passes
string input_format;
GetAclParams(parser_params, "input_format", input_format);
GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(ParseAclFormat(input_format) != SUCCESS,
return PARAM_INVALID, "Parse input_format failed");

string dynamic_input_str;
GetAclParams(parser_params, "is_dynamic_input", dynamic_input_str);
GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(!CheckInputTrueOrFalse(dynamic_input_str, "is_dynamic_input"),
return PARAM_INVALID, "Parse is_dynamic_input failed");
bool is_dynamic_input = dynamic_input_str == "true" ? true : false;

string input_shape;
GetAclParams(parser_params, "input_shape", input_shape);
GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(ParseAclShape(input_shape, is_dynamic_input) != SUCCESS,
return PARAM_INVALID, "Parse input_shape failed");

string out_nodes;
GetAclParams(parser_params, "out_nodes", out_nodes);
GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(ParseAclOutputNodes(out_nodes) != SUCCESS,
return PARAM_INVALID, "Parse out_nodes failed");


string is_output_adjust_hw_layout;
GetAclParams(parser_params, "is_output_adjust_hw_layout", is_output_adjust_hw_layout);
GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(ParseAclOutputFp16NodesFormat(is_output_adjust_hw_layout) != SUCCESS,
return PARAM_INVALID, "Parse is_output_adjust_hw_layout failed");

string op_conf_str;
GetAclParams(parser_params, "op_name_map", op_conf_str);
GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(ParseAclOpConf(op_conf_str.c_str()) != SUCCESS,
return PARAM_INVALID, "Parse op_name_map failed");

GetAclParams(parser_params, "output", graph_name);

string enable_scope_fusion_passes;
GetAclParams(parser_params, "enable_scope_fusion_passes", enable_scope_fusion_passes);
GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(ParseAclEnableScope(enable_scope_fusion_passes) != SUCCESS,
return PARAM_INVALID, "Parse enable_scope_fusion_passes failed");

return SUCCESS;
}

domi::Status AclGrphParseUtil::ParseParamsAfterGraph(ge::Graph &graph,
const std::map<std::string, std::string> &parser_params) {
// support paragrams: input_fp16_nodes, is_input_adjust_hw_layout, compress_weight_conf,
// log
compute_graph = GraphUtils::GetComputeGraph(graph);

string input_fp16_nodes;
GetAclParams(parser_params, "input_fp16_nodes", input_fp16_nodes);

string is_input_adjust_hw_layout;
GetAclParams(parser_params, "is_input_adjust_hw_layout", is_input_adjust_hw_layout);
GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(ParseAclInputFp16Nodes(compute_graph, input_fp16_nodes, is_input_adjust_hw_layout) != SUCCESS,
return PARAM_INVALID, "Parse input_fp16_nodes failed");
//GE_RETURN_IF_ERROR(CheckInputShapeNode(compute_graph, is_dynamic_input));
string compress_weight_conf;
GetAclParams(parser_params, "compress_weight_conf", compress_weight_conf);
GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(ParseAclWeightCompressConf(compute_graph, compress_weight_conf) != SUCCESS,
return PARAM_INVALID, "Parse compress_weight_conf failed");
return SUCCESS;
}

namespace parser {
FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY std::string RealPath(const char *path) {
if (path == nullptr) {


+ 30
- 2
parser/common/acl_graph_parser_util.h View File

@@ -37,13 +37,41 @@ class AclGrphParseUtil {
domi::Status LoadOpsProtoLib();
void SaveCustomCaffeProtoPath();
domi::Status AclParserInitialize(const std::map<std::string, std::string> &options);
domi::Status SetDefaultOutputNode(ge::Graph &graph);

domi::Status SetOutputNodeInfo(ge::Graph &graph,
const std::map<std::string, std::string> &parser_params);
domi::Status ParseParamsBeforeGraph(const std::map<std::string, std::string> &parser_params,
std::string &graph_name);
domi::Status ParseParamsAfterGraph(ge::Graph &graph,
const std::map<std::string, std::string> &parser_params);
domi::Status ParseOutputInfo(ge::Graph &graph,
const std::map<std::string, std::string> &parser_params);
private:
bool parser_initialized = false;
domi::Status GetOutputLeaf(NodePtr node, std::vector<std::pair<ge::NodePtr, int32_t>> &output_nodes_info);
void GetOutputNodesNameAndIndex(std::vector<std::pair<ge::NodePtr, int32_t>> &output_nodes_info,
std::vector<std::string> &output_nodes_name);
domi::Status ParseAclFormat(const std::string &input_format);
bool ParseInputShape(const std::string &input_shape,
unordered_map<std::string, vector<int64_t>> &shape_map,
vector<pair<std::string, vector<int64_t>>> &user_shape_map,
bool is_dynamic_input);
domi::Status ParseAclShape(const std::string &input_shape, bool is_dynamic_input);
domi::Status ParseAclOutputNodes(const std::string &out_nodes);
domi::Status ParseAclOutputFp16NodesFormat(const std::string &is_output_fp16);
domi::Status ParseAclOpConf(const char *op_conf);
domi::Status ParseAclEnableScope(const std::string &enable_scope_fusion_passes);
static void AddAttrsForInputNodes(const vector<string> &adjust_fp16_format_vec,
const string &fp16_nodes_name, uint32_t index,
OpDescPtr &op_desc);
domi::Status ParseAclInputFp16Nodes(const ComputeGraphPtr &graph,
const string &input_fp16_nodes,
const string &is_input_adjust_hw_layout);
domi::Status ParseAclWeightCompressConf(const ComputeGraphPtr &graph,
const string &compress_weight_conf);
domi::Status ParseAclOutputType(const std::string &output_type,
std::map<std::string, vector<std::string>> &output_node_dt_map);
domi::Status GetDefaultOutInfo(ge::ComputeGraphPtr &compute_graph,
std::vector<std::pair<ge::NodePtr, int32_t>> &output_nodes_info);
};

namespace parser {


+ 48
- 1
parser/tensorflow/tensorflow_parser.cc View File

@@ -113,13 +113,60 @@ graphStatus aclgrphParseTensorFlow(const char *model_file, ge::Graph &graph) {
return ge::FAILED;
}

if (acl_graph_parse_util.SetDefaultOutputNode(graph) != ge::SUCCESS) {
std::map<string, string> &parser_params;
if (acl_graph_parse_util.SetOutputNodeInfo(graph, parser_params) != ge::SUCCESS) {
GELOGE(ret, "Set graph %s default output node failed.", graph.GetName().c_str());
return ge::FAILED;
}
GELOGI("Parser graph %s success.", graph.GetName().c_str());
return ge::SUCCESS;
}

graphStatus aclgrphParseTensorFlow(const char *model_file,
const std::map<std::string, std::string> &parser_params,
ge::Graph &graph) {
GE_CHECK_NOTNULL(model_file);
GetParserContext().type = domi::TENSORFLOW;
std::map<string, string> options;
options.insert(std::pair<string, string>(string(ge::FRAMEWORK_TYPE), to_string(ge::TENSORFLOW)));

// load custom plugin so and proto
AclGrphParseUtil acl_graph_parse_util;
(void)acl_graph_parse_util.AclParserInitialize(options);

string output_name;
if (acl_graph_parse_util.ParseParamsBeforeGraph(parser_params, output_name) != ge::SUCCESS) {
GELOGE(ge::FAILED, "Parser params before graph failed.");
return ge::FAILED;
}
// Create an empty computegraph
string graph_name = output_name.empty() ? "tmpGraph", output_name;
ge::ComputeGraphPtr compute_graph = ge::parser::MakeShared<ge::ComputeGraph>(graph_name);
GE_CHECK_NOTNULL(compute_graph);

graph = ge::GraphUtils::CreateGraphFromComputeGraph(compute_graph);
auto model_parser = domi::ModelParserFactory::Instance()->CreateModelParser(domi::TENSORFLOW);
GE_CHECK_NOTNULL(model_parser);

// parse tensorflow model_file to GE graph
ge::graphStatus ret = model_parser->Parse(model_file, graph);
if (ret != ge::SUCCESS) {
GELOGE(ret, "Parser graph %s failed.", graph.GetName().c_str());
return ge::FAILED;
}

if (acl_graph_parse_util.ParseParamsAfterGraph(graph, parser_params) != ge::SUCCESS) {
GELOGE(ge::FAILED, "Parser params after graph failed.");
return ge::FAILED;
}

if (acl_graph_parse_util.SetOutputNodeInfo(graph, parser_params) != ge::SUCCESS) {
GELOGE(ge::FAILED, "Set graph %s default output node failed.", graph.GetName().c_str());
return ge::FAILED;
}
GELOGI("AclgrphParse graph %s success.", graph.GetName().c_str());
return ge::SUCCESS;
}
} // namespace ge

namespace ge {


Loading…
Cancel
Save