From 9ca2b4584dd015006992a04174e4cc6a8a8caa7f Mon Sep 17 00:00:00 2001 From: bzhang Date: Tue, 17 Aug 2021 10:07:57 +0800 Subject: [PATCH 1/8] tensorflow serializer version 1 --- CMakeLists.txt | 6 +- tools/convert_tool/CMakeLists.txt | 42 + tools/convert_tool/convert_tool.cpp | 6 + .../convert_tool/tensorflow/attr_value.proto | 62 + tools/convert_tool/tensorflow/function.proto | 101 + tools/convert_tool/tensorflow/graph.proto | 56 + tools/convert_tool/tensorflow/node_def.proto | 63 + tools/convert_tool/tensorflow/op_def.proto | 157 ++ .../tensorflow/resource_handle.proto | 29 + tools/convert_tool/tensorflow/tensor.proto | 88 + .../tensorflow/tensor_shape.proto | 45 + tools/convert_tool/tensorflow/tf2tengine.cpp | 1934 +++++++++++++++++ tools/convert_tool/tensorflow/tf2tengine.hpp | 248 +++ tools/convert_tool/tensorflow/types.proto | 66 + tools/convert_tool/tensorflow/versions.proto | 31 + 15 files changed, 2931 insertions(+), 3 deletions(-) create mode 100644 tools/convert_tool/tensorflow/attr_value.proto create mode 100644 tools/convert_tool/tensorflow/function.proto create mode 100644 tools/convert_tool/tensorflow/graph.proto create mode 100644 tools/convert_tool/tensorflow/node_def.proto create mode 100644 tools/convert_tool/tensorflow/op_def.proto create mode 100644 tools/convert_tool/tensorflow/resource_handle.proto create mode 100644 tools/convert_tool/tensorflow/tensor.proto create mode 100644 tools/convert_tool/tensorflow/tensor_shape.proto create mode 100644 tools/convert_tool/tensorflow/tf2tengine.cpp create mode 100644 tools/convert_tool/tensorflow/tf2tengine.hpp create mode 100644 tools/convert_tool/tensorflow/types.proto create mode 100644 tools/convert_tool/tensorflow/versions.proto diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b0597475..5177cb4f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,15 +49,15 @@ IF (NOT CMAKE_BUILD_TYPE) ENDIF() # Module options -OPTION (TENGINE_BUILD_BENCHMARK "Build benchmark" ON) -OPTION (TENGINE_BUILD_EXAMPLES "Build examples" ON) +OPTION (TENGINE_BUILD_BENCHMARK "Build benchmark" OFF) +OPTION (TENGINE_BUILD_EXAMPLES "Build examples" OFF) OPTION (TENGINE_BUILD_DEMO "Build demos" OFF) OPTION (TENGINE_BUILD_TESTS "Build tests" OFF) OPTION (TENGINE_BUILD_CPP_API "Build C++ API" OFF) # Tools options # Tools -OPTION (TENGINE_BUILD_CONVERT_TOOL "Build convert tool" OFF) +OPTION (TENGINE_BUILD_CONVERT_TOOL "Build convert tool" ON) OPTION (TENGINE_BUILD_QUANT_TOOL "Build quantization tool" OFF) # Multithreading option diff --git a/tools/convert_tool/CMakeLists.txt b/tools/convert_tool/CMakeLists.txt index 2537bbac5..a7d6d03da 100644 --- a/tools/convert_tool/CMakeLists.txt +++ b/tools/convert_tool/CMakeLists.txt @@ -61,6 +61,47 @@ list(APPEND CAFFE_SERIALIZER_SRCS ${CAFFE_PROTO_SRC}) # NCNN file(GLOB_RECURSE NCNN_SERIALIZER_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/ncnn/*.cpp") +# TENSORFLOW +file(GLOB_RECURSE TF_SERIALIZER_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/tensorflow/*.cpp") + +list(APPEND TENGINE_LIB_SRCS ${serializer_src}) + +# the generated pb.cc +set(TF_PROTO_SRC ${CMAKE_CURRENT_BINARY_DIR}/tensorflow/graph.pb.cc + ${CMAKE_CURRENT_BINARY_DIR}/tensorflow/function.pb.cc + ${CMAKE_CURRENT_BINARY_DIR}/tensorflow/node_def.pb.cc + ${CMAKE_CURRENT_BINARY_DIR}/tensorflow/op_def.pb.cc + ${CMAKE_CURRENT_BINARY_DIR}/tensorflow/attr_value.pb.cc + ${CMAKE_CURRENT_BINARY_DIR}/tensorflow/tensor.pb.cc + ${CMAKE_CURRENT_BINARY_DIR}/tensorflow/tensor_shape.pb.cc + ${CMAKE_CURRENT_BINARY_DIR}/tensorflow/types.pb.cc + ${CMAKE_CURRENT_BINARY_DIR}/tensorflow/versions.pb.cc + ${CMAKE_CURRENT_BINARY_DIR}/tensorflow/resource_handle.pb.cc) + +set(TF_PROTO_PATH ${CMAKE_CURRENT_SOURCE_DIR}/tensorflow) +set(TF_PROTO_OUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/tensorflow) + +ADD_CUSTOM_COMMAND(OUTPUT ${TF_PROTO_SRC} + COMMAND mkdir -p ${TF_PROTO_OUT_PATH} + COMMAND ${Protobuf_PROTOC_EXECUTABLE} --cpp_out=${TF_PROTO_OUT_PATH} --proto_path=${TF_PROTO_PATH} ${TF_PROTO_PATH}/graph.proto + COMMAND ${Protobuf_PROTOC_EXECUTABLE} --cpp_out=${TF_PROTO_OUT_PATH} --proto_path=${TF_PROTO_PATH} ${TF_PROTO_PATH}/function.proto + COMMAND ${Protobuf_PROTOC_EXECUTABLE} --cpp_out=${TF_PROTO_OUT_PATH} --proto_path=${TF_PROTO_PATH} ${TF_PROTO_PATH}/node_def.proto + COMMAND ${Protobuf_PROTOC_EXECUTABLE} --cpp_out=${TF_PROTO_OUT_PATH} --proto_path=${TF_PROTO_PATH} ${TF_PROTO_PATH}/op_def.proto + COMMAND ${Protobuf_PROTOC_EXECUTABLE} --cpp_out=${TF_PROTO_OUT_PATH} --proto_path=${TF_PROTO_PATH} ${TF_PROTO_PATH}/attr_value.proto + COMMAND ${Protobuf_PROTOC_EXECUTABLE} --cpp_out=${TF_PROTO_OUT_PATH} --proto_path=${TF_PROTO_PATH} ${TF_PROTO_PATH}/tensor.proto + COMMAND ${Protobuf_PROTOC_EXECUTABLE} --cpp_out=${TF_PROTO_OUT_PATH} --proto_path=${TF_PROTO_PATH} ${TF_PROTO_PATH}/tensor_shape.proto + COMMAND ${Protobuf_PROTOC_EXECUTABLE} --cpp_out=${TF_PROTO_OUT_PATH} --proto_path=${TF_PROTO_PATH} ${TF_PROTO_PATH}/types.proto + COMMAND ${Protobuf_PROTOC_EXECUTABLE} --cpp_out=${TF_PROTO_OUT_PATH} --proto_path=${TF_PROTO_PATH} ${TF_PROTO_PATH}/versions.proto + COMMAND ${Protobuf_PROTOC_EXECUTABLE} --cpp_out=${TF_PROTO_OUT_PATH} --proto_path=${TF_PROTO_PATH} ${TF_PROTO_PATH}/resource_handle.proto + #COMMAND mv ${TF_PROTO_OUT_PATH}/*.pb.h ${TF_PROTO_PATH}/../include/ +) + +ADD_CUSTOM_TARGET(TF_SERIALIZER_TARGET DEPENDS ${TF_PROTO_OUT_PATH}) + +include_directories(${TF_PROTO_OUT_PATH}) + +list(APPEND TF_SERIALIZER_SRCS ${TF_PROTO_SRC}) + # SAVE GRAPH FILE(GLOB_RECURSE SAVE_GRAPH_SRCS "${CMAKE_SOURCE_DIR}/tools/save_graph/*.cpp" "${CMAKE_SOURCE_DIR}/tools/save_graph/*.c") @@ -73,6 +114,7 @@ FILE(GLOB_RECURSE CONVERT_TOOL_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/convert_tool.cp list(APPEND CONVERT_TOOL_SRCS ${ONNX_SERIALIZER_SRCS}) list(APPEND CONVERT_TOOL_SRCS ${CAFFE_SERIALIZER_SRCS}) list(APPEND CONVERT_TOOL_SRCS ${NCNN_SERIALIZER_SRCS}) +list(APPEND CONVERT_TOOL_SRCS ${TF_SERIALIZER_SRCS}) list(APPEND CONVERT_TOOL_SRCS ${SAVE_GRAPH_SRCS}) list(APPEND CONVERT_TOOL_SRCS ${GRAPH_OPT_SRCS}) diff --git a/tools/convert_tool/convert_tool.cpp b/tools/convert_tool/convert_tool.cpp index 491f39e7d..9221bb44f 100644 --- a/tools/convert_tool/convert_tool.cpp +++ b/tools/convert_tool/convert_tool.cpp @@ -31,6 +31,7 @@ #include "onnx/onnx2tengine.hpp" #include "caffe/caffe2tengine.hpp" #include "ncnn/ncnn2tengine.hpp" +#include "tensorflow/tf2tengine.hpp" #include "utils/graph_optimizer/graph_opt.hpp" const char* help_params = "[Convert Tools Info]: optional arguments:\n" @@ -178,6 +179,11 @@ int main(int argc, char* argv[]) ncnn_serializer n2t; graph = n2t.ncnn2tengine(model_file, proto_file); } + else if (file_format == "tensorflow") + { + tensorflow_serializer tf2t; + graph = tf2t.tensorflow2tengine(model_file); + } else { fprintf(stderr, "Convert model failed: support onnx only...\n"); diff --git a/tools/convert_tool/tensorflow/attr_value.proto b/tools/convert_tool/tensorflow/attr_value.proto new file mode 100644 index 000000000..74e2a3b0a --- /dev/null +++ b/tools/convert_tool/tensorflow/attr_value.proto @@ -0,0 +1,62 @@ +syntax = "proto3"; + +package tensorflow; +option cc_enable_arenas = true; +option java_outer_classname = "AttrValueProtos"; +option java_multiple_files = true; +option java_package = "org.tensorflow.framework"; + +import "tensor.proto"; +import "tensor_shape.proto"; +import "types.proto"; + +// Protocol buffer representing the value for an attr used to configure an Op. +// Comment indicates the corresponding attr type. Only the field matching the +// attr type may be filled. +message AttrValue { + // LINT.IfChange + message ListValue { + repeated bytes s = 2; // "list(string)" + repeated int64 i = 3 [packed = true]; // "list(int)" + repeated float f = 4 [packed = true]; // "list(float)" + repeated bool b = 5 [packed = true]; // "list(bool)" + repeated DataType type = 6 [packed = true]; // "list(type)" + repeated TensorShapeProto shape = 7; // "list(shape)" + repeated TensorProto tensor = 8; // "list(tensor)" + repeated NameAttrList func = 9; // "list(attr)" + } + // LINT.ThenChange(https://www.tensorflow.org/code/tensorflow/c/c_api.cc) + + oneof value { + bytes s = 2; // "string" + int64 i = 3; // "int" + float f = 4; // "float" + bool b = 5; // "bool" + DataType type = 6; // "type" + TensorShapeProto shape = 7; // "shape" + TensorProto tensor = 8; // "tensor" + ListValue list = 1; // any "list(...)" + + // "func" represents a function. func.name is a function's name or + // a primitive op's name. func.attr.first is the name of an attr + // defined for that function. func.attr.second is the value for + // that attr in the instantiation. + NameAttrList func = 10; + + // This is a placeholder only used in nodes defined inside a + // function. It indicates the attr value will be supplied when + // the function is instantiated. For example, let us suppose a + // node "N" in function "FN". "N" has an attr "A" with value + // placeholder = "foo". When FN is instantiated with attr "foo" + // set to "bar", the instantiated node N's attr A will have been + // given the value "bar". + string placeholder = 9; + } +} + +// A list of attr names and their values. The whole list is attached +// with a string name. E.g., MatMul[T=float]. +message NameAttrList { + string name = 1; + map attr = 2; +} diff --git a/tools/convert_tool/tensorflow/function.proto b/tools/convert_tool/tensorflow/function.proto new file mode 100644 index 000000000..ccb12cb4f --- /dev/null +++ b/tools/convert_tool/tensorflow/function.proto @@ -0,0 +1,101 @@ +syntax = "proto3"; + +package tensorflow; +option cc_enable_arenas = true; +option java_outer_classname = "FunctionProtos"; +option java_multiple_files = true; +option java_package = "org.tensorflow.framework"; + +import "attr_value.proto"; +import "node_def.proto"; +import "op_def.proto"; + +// A library is a set of named functions. +message FunctionDefLibrary { + repeated FunctionDef function = 1; + repeated GradientDef gradient = 2; +} + +// A function can be instantiated when the runtime can bind every attr +// with a value. When a GraphDef has a call to a function, it must +// have binding for every attr defined in the signature. +// +// TODO(zhifengc): +// * device spec, etc. +message FunctionDef { + // The definition of the function's name, arguments, return values, + // attrs etc. + OpDef signature = 1; + + // Attributes specific to this function definition. + map attr = 5; + + // NOTE: field id 2 deleted on Jan 11, 2016, GraphDef version 21. + + // In both of the following fields, there is the need to specify an + // output that is used as either the input to another node (in + // `node_def`) or as a return value of the function (in `ret`). + // Unlike the NodeDefs in GraphDef, we need to be able to specify a + // list in some cases (instead of just single outputs). Also, we + // need to be able to deal with lists of unknown length (so the + // output index may not be known at function definition time). So + // we use the following format instead: + // * "fun_in" where "fun_in" is the name of a function input arg in + // the `signature` field above. This represents that input, whether + // it is a single tensor or a list. + // * "fun_in:0" gives the first element of a function input arg (a + // non-list input is considered a list of length 1 for these + // purposes). + // * "node:out" where "node" is the name of a node in `node_def` and + // "out" is the name one of its op's output arguments (the name + // comes from the OpDef of the node's op). This represents that + // node's output, whether it is a single tensor or a list. + // Note: We enforce that an op's output arguments are never + // renamed in the backwards-compatibility test. + // * "node:out:0" gives the first element of a node output arg (a + // non-list output is considered a list of length 1 for these + // purposes). + // + // NOT CURRENTLY SUPPORTED (but may be in the future): + // * "node:out:-1" gives last element in a node output list + // * "node:out:1:" gives a list with all but the first element in a + // node output list + // * "node:out::-1" gives a list with all but the last element in a + // node output list + + // The body of the function. Unlike the NodeDefs in a GraphDef, attrs + // may have values of type `placeholder` and the `input` field uses + // the "output" format above. + + // By convention, "op" in node_def is resolved by consulting with a + // user-defined library first. If not resolved, "func" is assumed to + // be a builtin op. + repeated NodeDef node_def = 3; + + // A mapping from the output arg names from `signature` to the + // outputs from `node_def` that should be returned by the function. + map ret = 4; +} + +// GradientDef defines the gradient function of a function defined in +// a function library. +// +// A gradient function g (specified by gradient_func) for a function f +// (specified by function_name) must follow the following: +// +// The function 'f' must be a numerical function which takes N inputs +// and produces M outputs. Its gradient function 'g', which is a +// function taking N + M inputs and produces N outputs. +// +// I.e. if we have +// (y1, y2, ..., y_M) = f(x1, x2, ..., x_N), +// then, g is +// (dL/dx1, dL/dx2, ..., dL/dx_N) = g(x1, x2, ..., x_N, +// dL/dy1, dL/dy2, ..., dL/dy_M), +// where L is a scalar-value function of (x1, x2, ..., xN) (e.g., the +// loss function). dL/dx_i is the partial derivative of L with respect +// to x_i. +message GradientDef { + string function_name = 1; // The function name. + string gradient_func = 2; // The gradient function's name. +} diff --git a/tools/convert_tool/tensorflow/graph.proto b/tools/convert_tool/tensorflow/graph.proto new file mode 100644 index 000000000..65119189f --- /dev/null +++ b/tools/convert_tool/tensorflow/graph.proto @@ -0,0 +1,56 @@ +syntax = "proto3"; + +package tensorflow; +option cc_enable_arenas = true; +option java_outer_classname = "GraphProtos"; +option java_multiple_files = true; +option java_package = "org.tensorflow.framework"; + +import "node_def.proto"; +import "function.proto"; +import "versions.proto"; + +// Represents the graph of operations +message GraphDef { + repeated NodeDef node = 1; + + // Compatibility versions of the graph. See core/public/version.h for version + // history. The GraphDef version is distinct from the TensorFlow version, and + // each release of TensorFlow will support a range of GraphDef versions. + VersionDef versions = 4; + + // Deprecated single version field; use versions above instead. Since all + // GraphDef changes before "versions" was introduced were forward + // compatible, this field is entirely ignored. + int32 version = 3 [deprecated = true]; + + // EXPERIMENTAL. DO NOT USE OR DEPEND ON THIS YET. + // + // "library" provides user-defined functions. + // + // Naming: + // * library.function.name are in a flat namespace. + // NOTE: We may need to change it to be hierarchical to support + // different orgs. E.g., + // { "/google/nn", { ... }}, + // { "/google/vision", { ... }} + // { "/org_foo/module_bar", { ... }} + // map named_lib; + // * If node[i].op is the name of one function in "library", + // node[i] is deemed as a function call. Otherwise, node[i].op + // must be a primitive operation supported by the runtime. + // + // + // Function call semantics: + // + // * The callee may start execution as soon as some of its inputs + // are ready. The caller may want to use Tuple() mechanism to + // ensure all inputs are ready in the same time. + // + // * The consumer of return values may start executing as soon as + // the return values the consumer depends on are ready. The + // consumer may want to use Tuple() mechanism to ensure the + // consumer does not start until all return values of the callee + // function are ready. + FunctionDefLibrary library = 2; +}; diff --git a/tools/convert_tool/tensorflow/node_def.proto b/tools/convert_tool/tensorflow/node_def.proto new file mode 100644 index 000000000..e6d545ad5 --- /dev/null +++ b/tools/convert_tool/tensorflow/node_def.proto @@ -0,0 +1,63 @@ +syntax = "proto3"; + +package tensorflow; +option cc_enable_arenas = true; +option java_outer_classname = "NodeProto"; +option java_multiple_files = true; +option java_package = "org.tensorflow.framework"; + +import "attr_value.proto"; + +message NodeDef { + // The name given to this operator. Used for naming inputs, + // logging, visualization, etc. Unique within a single GraphDef. + // Must match the regexp "[A-Za-z0-9.][A-Za-z0-9_./]*". + string name = 1; + + // The operation name. There may be custom parameters in attrs. + // Op names starting with an underscore are reserved for internal use. + string op = 2; + + // Each input is "node:src_output" with "node" being a string name and + // "src_output" indicating which output tensor to use from "node". If + // "src_output" is 0 the ":0" suffix can be omitted. Regular inputs + // may optionally be followed by control inputs that have the format + // "^node". + repeated string input = 3; + + // A (possibly partial) specification for the device on which this + // node should be placed. + // The expected syntax for this string is as follows: + // + // DEVICE_SPEC ::= PARTIAL_SPEC + // + // PARTIAL_SPEC ::= ("/" CONSTRAINT) * + // CONSTRAINT ::= ("job:" JOB_NAME) + // | ("replica:" [1-9][0-9]*) + // | ("task:" [1-9][0-9]*) + // | ( ("gpu" | "cpu") ":" ([1-9][0-9]* | "*") ) + // + // Valid values for this string include: + // * "/job:worker/replica:0/task:1/gpu:3" (full specification) + // * "/job:worker/gpu:3" (partial specification) + // * "" (no specification) + // + // If the constraints do not resolve to a single device (or if this + // field is empty or not present), the runtime will attempt to + // choose a device automatically. + string device = 4; + + // Operation-specific graph-construction-time configuration. + // Note that this should include all attrs defined in the + // corresponding OpDef, including those with a value matching + // the default -- this allows the default to change and makes + // NodeDefs easier to interpret on their own. However, if + // an attr with a default is not specified in this list, the + // default will be used. + // The "names" (keys) must match the regexp "[a-z][a-z0-9_]+" (and + // one of the names from the corresponding OpDef's attr field). + // The values must have a type matching the corresponding OpDef + // attr's type field. + // TODO(josh11b): Add some examples here showing best practices. + map attr = 5; +}; diff --git a/tools/convert_tool/tensorflow/op_def.proto b/tools/convert_tool/tensorflow/op_def.proto new file mode 100644 index 000000000..baf68eaad --- /dev/null +++ b/tools/convert_tool/tensorflow/op_def.proto @@ -0,0 +1,157 @@ +syntax = "proto3"; + +package tensorflow; +option cc_enable_arenas = true; +option java_outer_classname = "OpDefProtos"; +option java_multiple_files = true; +option java_package = "org.tensorflow.framework"; + +import "attr_value.proto"; +import "types.proto"; + +// Defines an operation. A NodeDef in a GraphDef specifies an Op by +// using the "op" field which should match the name of a OpDef. +message OpDef { + // Op names starting with an underscore are reserved for internal use. + // Names should be CamelCase and match the regexp "[A-Z][a-zA-Z0-9_]*". + string name = 1; + + // For describing inputs and outputs. + message ArgDef { + // Name for the input/output. Should match the regexp "[a-z][a-z0-9_]*". + string name = 1; + + // Human readable description. + string description = 2; + + // Describes the type of one or more tensors that are accepted/produced + // by this input/output arg. The only legal combinations are: + // * For a single tensor: either the "type" field is set or the + // "type_attr" field is set to the name of an attr with type "type". + // * For a sequence of tensors with the same type: the "number_attr" + // field will be set to the name of an attr with type "int", and + // either the "type" or "type_attr" field will be set as for + // single tensors. + // * For a sequence of tensors, the "type_list_attr" field will be set + // to the name of an attr with type "list(type)". + DataType type = 3; + string type_attr = 4; // if specified, attr must have type "type" + string number_attr = 5; // if specified, attr must have type "int" + // If specified, attr must have type "list(type)", and none of + // type, type_attr, and number_attr may be specified. + string type_list_attr = 6; + + // For inputs: if true, the inputs are required to be refs. + // By default, inputs can be either refs or non-refs. + // For outputs: if true, outputs are refs, otherwise they are not. + bool is_ref = 16; + }; + + // Description of the input(s). + repeated ArgDef input_arg = 2; + + // Description of the output(s). + repeated ArgDef output_arg = 3; + + // Description of the graph-construction-time configuration of this + // Op. That is to say, this describes the attr fields that will + // be specified in the NodeDef. + message AttrDef { + // A descriptive name for the argument. May be used, e.g. by the + // Python client, as a keyword argument name, and so should match + // the regexp "[a-z][a-z0-9_]+". + string name = 1; + + // One of the type names from attr_value.proto ("string", "list(string)", + // "int", etc.). + string type = 2; + + // A reasonable default for this attribute if the user does not supply + // a value. If not specified, the user must supply a value. + AttrValue default_value = 3; + + // Human-readable description. + string description = 4; + + // TODO(josh11b): bool is_optional? + + // --- Constraints --- + // These constraints are only in effect if specified. Default is no + // constraints. + + // For type == "int", this is a minimum value. For "list(___)" + // types, this is the minimum length. + bool has_minimum = 5; + int64 minimum = 6; + + // The set of allowed values. Has type that is the "list" version + // of the "type" field above (uses the "list" field of AttrValue). + // If type == "type" or "list(type)" above, then the "type" field + // of "allowed_values.list" has the set of allowed DataTypes. + // If type == "string" or "list(string)", then the "s" field of + // "allowed_values.list" has the set of allowed strings. + AttrValue allowed_values = 7; + } + repeated AttrDef attr = 4; + + // Optional deprecation based on GraphDef versions. + OpDeprecation deprecation = 8; + + // One-line human-readable description of what the Op does. + string summary = 5; + + // Additional, longer human-readable description of what the Op does. + string description = 6; + + // ------------------------------------------------------------------------- + // Which optimizations this operation can participate in. + + // True if the operation is commutative ("op(a,b) == op(b,a)" for all inputs) + bool is_commutative = 18; + + // If is_aggregate is true, then this operation accepts N >= 2 + // inputs and produces 1 output all of the same type. Should be + // associative and commutative, and produce output with the same + // shape as the input. The optimizer may replace an aggregate op + // taking input from multiple devices with a tree of aggregate ops + // that aggregate locally within each device (and possibly within + // groups of nearby devices) before communicating. + // TODO(josh11b): Implement that optimization. + bool is_aggregate = 16; // for things like add + + // Other optimizations go here, like + // can_alias_input, rewrite_when_output_unused, partitioning_strategy, etc. + + // ------------------------------------------------------------------------- + // Optimization constraints. + + // By default Ops may be moved between devices. Stateful ops should + // either not be moved, or should only be moved if that state can also + // be moved (e.g. via some sort of save / restore). + // Stateful ops are guaranteed to never be optimized away by Common + // Subexpression Elimination (CSE). + bool is_stateful = 17; // for things like variables, queue + + // ------------------------------------------------------------------------- + // Non-standard options. + + // By default, all inputs to an Op must be initialized Tensors. Ops + // that may initialize tensors for the first time should set this + // field to true, to allow the Op to take an uninitialized Tensor as + // input. + bool allows_uninitialized_input = 19; // for Assign, etc. +}; + +// Information about version-dependent deprecation of an op +message OpDeprecation { + // First GraphDef version at which the op is disallowed. + int32 version = 1; + + // Explanation of why it was deprecated and what to use instead. + string explanation = 2; +}; + +// A collection of OpDefs +message OpList { + repeated OpDef op = 1; +}; diff --git a/tools/convert_tool/tensorflow/resource_handle.proto b/tools/convert_tool/tensorflow/resource_handle.proto new file mode 100644 index 000000000..b1921337f --- /dev/null +++ b/tools/convert_tool/tensorflow/resource_handle.proto @@ -0,0 +1,29 @@ +syntax = "proto3"; + +package tensorflow; +option cc_enable_arenas = true; +option java_outer_classname = "ResourceHandle"; +option java_multiple_files = true; +option java_package = "org.tensorflow.framework"; + +// Protocol buffer representing a handle to a tensorflow resource. Handles are +// not valid across executions, but can be serialized back and forth from within +// a single run. +message ResourceHandleProto { + // Unique name for the device containing the resource. + string device = 1; + + // Container in which this resource is placed. + string container = 2; + + // Unique name of this resource. + string name = 3; + + // Hash code for the type of the resource. Is only valid in the same device + // and in the same execution. + uint64 hash_code = 4; + + // For debug-only, the name of the type pointed to by this handle, if + // available. + string maybe_type_name = 5; +}; diff --git a/tools/convert_tool/tensorflow/tensor.proto b/tools/convert_tool/tensorflow/tensor.proto new file mode 100644 index 000000000..c79293023 --- /dev/null +++ b/tools/convert_tool/tensorflow/tensor.proto @@ -0,0 +1,88 @@ +syntax = "proto3"; + +package tensorflow; +option cc_enable_arenas = true; +option java_outer_classname = "TensorProtos"; +option java_multiple_files = true; +option java_package = "org.tensorflow.framework"; + +import "resource_handle.proto"; +import "tensor_shape.proto"; +import "types.proto"; + +// Protocol buffer representing a tensor. +message TensorProto { + DataType dtype = 1; + + // Shape of the tensor. TODO(touts): sort out the 0-rank issues. + TensorShapeProto tensor_shape = 2; + + // Only one of the representations below is set, one of "tensor_contents" and + // the "xxx_val" attributes. We are not using oneof because as oneofs cannot + // contain repeated fields it would require another extra set of messages. + + // Version number. + // + // In version 0, if the "repeated xxx" representations contain only one + // element, that element is repeated to fill the shape. This makes it easy + // to represent a constant Tensor with a single value. + int32 version_number = 3; + + // Serialized raw tensor content from either Tensor::AsProtoTensorContent or + // memcpy in tensorflow::grpc::EncodeTensorToByteBuffer. This representation + // can be used for all tensor types. The purpose of this representation is to + // reduce serialization overhead during RPC call by avoiding serialization of + // many repeated small items. + bytes tensor_content = 4; + + // Type specific representations that make it easy to create tensor protos in + // all languages. Only the representation corresponding to "dtype" can + // be set. The values hold the flattened representation of the tensor in + // row major order. + + // DT_HALF. Note that since protobuf has no int16 type, we'll have some + // pointless zero padding for each value here. + repeated int32 half_val = 13 [packed = true]; + + // DT_FLOAT. + repeated float float_val = 5 [packed = true]; + + // DT_DOUBLE. + repeated double double_val = 6 [packed = true]; + + // DT_INT32, DT_INT16, DT_INT8, DT_UINT8. + repeated int32 int_val = 7 [packed = true]; + + // DT_STRING + repeated bytes string_val = 8; + + // DT_COMPLEX64. scomplex_val(2*i) and scomplex_val(2*i+1) are real + // and imaginary parts of i-th single precision complex. + repeated float scomplex_val = 9 [packed = true]; + + // DT_INT64 + repeated int64 int64_val = 10 [packed = true]; + + // DT_BOOL + repeated bool bool_val = 11 [packed = true]; + + // DT_COMPLEX128. dcomplex_val(2*i) and dcomplex_val(2*i+1) are real + // and imaginary parts of i-th double precision complex. + repeated double dcomplex_val = 12 [packed = true]; + + // DT_RESOURCE + repeated ResourceHandleProto resource_handle_val = 14; + + // DT_VARIANT + repeated VariantTensorDataProto variant_val = 15; +}; + +// Protocol buffer representing the serialization format of DT_VARIANT tensors. +message VariantTensorDataProto { + // Name of the type of objects being serialized. + string type_name = 1; + // Portions of the object that are not Tensors. + bytes metadata = 2; + // Tensors contained within objects being serialized. + repeated TensorProto tensors = 3; +} diff --git a/tools/convert_tool/tensorflow/tensor_shape.proto b/tools/convert_tool/tensorflow/tensor_shape.proto new file mode 100644 index 000000000..1ec3c5323 --- /dev/null +++ b/tools/convert_tool/tensorflow/tensor_shape.proto @@ -0,0 +1,45 @@ +// Protocol buffer representing the shape of tensors. + +syntax = "proto3"; +option cc_enable_arenas = true; +option java_outer_classname = "TensorShapeProtos"; +option java_multiple_files = true; +option java_package = "org.tensorflow.framework"; + +package tensorflow; + +// Dimensions of a tensor. +message TensorShapeProto { + // One dimension of the tensor. + message Dim { + // Size of the tensor in that dimension. + // This value must be >= -1, but values of -1 are reserved for "unknown" + // shapes (values of -1 mean "unknown" dimension). Certain wrappers + // that work with TensorShapeProto may fail at runtime when deserializing + // a TensorShapeProto containing a dim value of -1. + int64 size = 1; + + // Optional name of the tensor dimension. + string name = 2; + }; + + // Dimensions of the tensor, such as {"input", 30}, {"output", 40} + // for a 30 x 40 2D tensor. If an entry has size -1, this + // corresponds to a dimension of unknown size. The names are + // optional. + // + // The order of entries in "dim" matters: It indicates the layout of the + // values in the tensor in-memory representation. + // + // The first entry in "dim" is the outermost dimension used to layout the + // values, the last entry is the innermost dimension. This matches the + // in-memory layout of RowMajor Eigen tensors. + // + // If "dim.size()" > 0, "unknown_rank" must be false. + repeated Dim dim = 2; + + // If true, the number of dimensions in the shape is unknown. + // + // If true, "dim.size()" must be 0. + bool unknown_rank = 3; +}; diff --git a/tools/convert_tool/tensorflow/tf2tengine.cpp b/tools/convert_tool/tensorflow/tf2tengine.cpp new file mode 100644 index 000000000..50560ef6e --- /dev/null +++ b/tools/convert_tool/tensorflow/tf2tengine.cpp @@ -0,0 +1,1934 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * License); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* + * Copyright (c) 2021, OPEN AI LAB + * Author: bzhang@openailab.com + */ + +#include "tf2tengine.hpp" + +const int OP_VERSION = 1; + +bool tensorflow_serializer::find_op_load_method(const std::string& op_name) +{ + if (op_load_map.count(op_name)) + return true; + + return false; +} + +ir_tensor_t* tensorflow_serializer::find_tensor(ir_graph_t* graph, const std::string& tensor_name) +{ + for (uint16_t i = 0; i < graph->tensor_num; i++) + { + ir_tensor_t* tensor = get_ir_graph_tensor(graph, i); + if (tensor->name == tensor_name) + { + return tensor; + } + } + + return nullptr; +} + +static bool GetAttrValue(const tensorflow::NodeDef* node, const char* key, tensorflow::AttrValue& value) +{ + const google::protobuf::Map& attr = node->attr(); + + const google::protobuf::Map::const_iterator it = attr.find(key); + if(it != attr.end()) + { + value = it->second; + return true; + } + + return false; +} + +static void GetTensorContentAndDim(const tensorflow::TensorProto& tf_tensor, int* dims, void** mem_ptr, + std::string& layout, int dim_num) +{ + const tensorflow::TensorShapeProto& shape = tf_tensor.tensor_shape(); + + int elem_num = 1; + dim_num = shape.dim_size(); + + for(int i = 0; i < dim_num; i++) + { + elem_num *= shape.dim(i).size(); + dims[i] = shape.dim(i).size(); + } + + void* mem_buf = nullptr; + + if(tf_tensor.tensor_content().size()) + { + int content_size = tf_tensor.tensor_content().size(); + + mem_buf = malloc(content_size + 128); + void* src = ( void* )tf_tensor.tensor_content().c_str(); + memcpy(mem_buf, src, content_size); + } + else if(tf_tensor.dtype() == tensorflow::DataType::DT_FLOAT) + { + // in packed format + int data_num = tf_tensor.float_val_size(); + mem_buf = malloc(elem_num * sizeof(float)); + float* mem = ( float* )mem_buf; + + if(data_num >= elem_num) + { + for(int i = 0; i < elem_num; i++) + { + mem[i] = tf_tensor.float_val(i); + } + } + else + { + // data_num < elem_num + for(int i = 0; i < data_num; i++) + { + mem[i] = tf_tensor.float_val(i); + } + + for(int i = data_num; i < elem_num; i++) + { + mem[i] = mem[data_num - 1]; + } + } + } + else if(tf_tensor.dtype() == tensorflow::DataType::DT_INT32) + { + int data_num = tf_tensor.int_val_size(); + + mem_buf = malloc(elem_num * sizeof(int)); + + int* mem = ( int* )mem_buf; + + if(data_num >= elem_num) + { + for(int i = 0; i < elem_num; i++) + { + mem[i] = tf_tensor.int_val(i); + } + } + else + { + // data_num < elem_num + for(int i = 0; i < data_num; i++) + { + mem[i] = tf_tensor.int_val(i); + } + + for(int i = data_num; i < elem_num; i++) + { + mem[i] = mem[data_num - 1]; + } + } + } + + *mem_ptr = mem_buf; + + switch(dim_num) + { + case 0: + layout = "W"; + break; + case 1: + layout = "W"; + break; + case 2: + layout = "HW"; + break; + case 4: + layout = "NCHW"; + break; + default: + break; + } +} +int tensorflow_serializer::load_binary_file(std::string model_file) +{ + std::ifstream is(model_file.c_str(), std::ios::in | std::ios::binary); + + if(!is.is_open()) + { + TLOG_ERR("cannot open file: %s \n", model_file.c_str()); + return false; + } + + google::protobuf::io::IstreamInputStream input_stream(&is); + google::protobuf::io::CodedInputStream coded_input(&input_stream); + +#if GOOGLE_PROTOBUF_VERSION >= 3011000 + coded_input.SetTotalBytesLimit(INT_MAX); +#else + coded_input.SetTotalBytesLimit(INT_MAX, INT_MAX / 2); +#endif + bool ret = tf_net.ParseFromCodedStream(&coded_input); + + is.close(); + + if(!ret) + { + TLOG_ERR( "parse file: %s failed\n",model_file.c_str()); + return -1; + } + printf("graphd node numebr : %d \n", tf_net.node_size()); + return ret; +} +int load_const_tensor(TFNode* tf_node, ir_graph_t* graph) +{ + ir_node_t* node = create_ir_node(graph, tf_node->name.c_str(), OP_CONST, OP_VERSION); + ir_tensor_t* tensor = create_ir_tensor(graph, tf_node->name.c_str(),TENGINE_DT_FP32); + tensorflow::AttrValue value; + + const tensorflow::NodeDef* node_def = tf_node->pb_defs[0]; + if(GetAttrValue(node_def, "value", value)) + { + const tensorflow::TensorProto& tf_tensor = value.tensor(); + void* mem_ptr; + int* dims ; + int dim_num; + std::string layout; + GetTensorContentAndDim(tf_tensor, dims, &mem_ptr, layout, dim_num); + int mem_size = sizeof(float); + for(unsigned int i = 0; i < dim_num; i++) + { + mem_size *= dims[i]; + } + set_ir_tensor_shape(tensor, dims, dim_num); + + // SetTensorDim(tensor, dims, dims.size()); + } + set_ir_node_output_tensor(node, 0, tensor); + tf_node->ir_node = node; + tf_node->ir_tensor = tensor; +} + +int tensorflow_serializer::set_graph_input(ir_graph_t* graph) +{ + int node_num = tf_graph.seq_nodes.size(); + std::vector input_nodes; + for(int i = 0; i < node_num; i++) + { + TFNode* tf_node =tf_graph.seq_nodes[i]; + if(tf_node->op == "Placeholder") + { + ir_tensor_t* ir_tensor = create_ir_tensor(graph, tf_node->name.c_str(), TENGINE_DT_FP32); + tensorflow::AttrValue shape; + + int pb_defs_cnt = tf_node->pb_defs.size(); + int* dims; + if(pb_defs_cnt == 1) + { + if(GetAttrValue(tf_node->pb_defs[0], "shape", shape)) + { + int dim_size = shape.shape().dim_size(); + + dims = (int*)sys_malloc(dim_size); + memset(dims, 0, sizeof(int)*dim_size); + for(int i = 0; i < dim_size; ++i) + { + dims[i] = shape.shape().dim(i).size(); + } + set_ir_tensor_shape(ir_tensor, dims, dim_size); + } + } + else + { + tensorflow::AttrValue value; + const tensorflow::NodeDef* node_def = tf_node->pb_defs[pb_defs_cnt - 1]; + if(GetAttrValue(node_def, "value", value)) + { + const tensorflow::TensorProto& tf_tensor = value.tensor(); + + void* mem_ptr; + std::vector tf_dims; + std::string layout; + int dim_num = 0; + GetTensorContentAndDim(tf_tensor, dims, &mem_ptr, layout, dim_num); + dims = (int*)sys_malloc(tf_dims[0]); + memset(dims, 0, sizeof(int)*tf_dims[0]); + int* reshape_dim = ( int* )mem_ptr; + for(int i = 0; i < tf_dims[0]; i++) + { + dims[i] = reshape_dim[i]; + } + + for(unsigned int i = 0; i < tf_dims[0]; i++) + { + if(dims[i] == -1) + dims[i] = 1; + } + free(mem_ptr); + set_ir_tensor_shape(ir_tensor, dims, tf_dims[0]); + } + } + ir_node_t* node = create_ir_node(graph, tf_node->name.c_str(), OP_INPUT, OP_VERSION); + + int tensor_id = get_ir_tensor_index_from_name(graph, tf_node->name.c_str()); + + set_ir_node_output_tensor(node, 0, ir_tensor); + input_nodes.push_back(node->index); + } + } + int16_t* node_idx = (int16_t*)sys_malloc(sizeof(int16_t) * input_nodes.size()); + for (int i = 0; i < input_nodes.size(); i++) + { + node_idx[i] = input_nodes[i]; + } + set_ir_graph_input_node(graph, node_idx, input_nodes.size()); + return 0; +} +int tensorflow_serializer::construct_graph() +{ + int node_number = tf_net.node_size(); + std::unordered_map node_map; + + /* first scan, setup all nodes */ + printf("tf node_number: %d \n", tf_net.node_size()); + for(int i = 0; i < node_number; i++) + { + const tensorflow::NodeDef& node_param = tf_net.node(i); + + TFNode* tf_node = new TFNode(); + + tf_node->idx = i; + tf_node->name = node_param.name(); + tf_node->op = node_param.op(); + tf_node->pb_defs.push_back(&tf_net.node(i)); + + tf_graph.seq_nodes.push_back(tf_node); + + node_map[tf_node->name] = tf_node; + } + + /* the second scan, setup connections */ + for(int i = 0; i < node_number; i++) + { + const tensorflow::NodeDef& node_param = tf_net.node(i); + const std::string& name = node_param.name(); + + TFNode* cur_node = node_map[name]; + + for(int j = 0; j < node_param.input_size(); j++) + { + const std::string& input_name = node_param.input(j); + std::string::size_type pos = input_name.find(":"); + std::string cleanup_name; + + if(pos == std::string::npos) + pos = input_name.size(); + + if(input_name[0] == '^') + cleanup_name = input_name.substr(1, pos); + else + cleanup_name = input_name.substr(0, pos); + + TFNode* input_node = node_map[cleanup_name]; + + if(input_node == nullptr) + { + TLOG_ERR("cannot find input: %s for node: %s \n", input_name.c_str(), name.c_str()); + return false; + } + + cur_node->inputs.push_back(input_node); + input_node->outputs.push_back(cur_node); + } + } + return 0; +} +int DisconnectNode(TFNode* cur_node) +{ + TFNode* input_node; + + for(unsigned int i = 0; i < cur_node->inputs.size(); i++) + { + input_node = cur_node->inputs[i]; + + auto ir = input_node->outputs.begin(); + + while(ir != input_node->outputs.end()) + { + if(*ir != cur_node) + ir++; + else + break; + } + + if(ir == input_node->outputs.end()) + { + TLOG_ERR("ERROR on node connection!!\n"); + } + + input_node->outputs.erase(ir); + } + + cur_node->inputs.clear(); + + TFNode* output_node; + + for(unsigned int i = 0; i < cur_node->outputs.size(); i++) + { + output_node = cur_node->outputs[i]; + + auto ir = output_node->inputs.begin(); + + while(ir != output_node->inputs.end()) + { + if(*ir != cur_node) + ir++; + else + break; + } + + if(ir == output_node->inputs.end()) + { + TLOG_ERR("ERROR on node connection!!\n"); + } + + output_node->inputs.erase(ir); + } + + cur_node->outputs.clear(); +} + +int MergeParentNode(TFNode* base_node, TFNode* parent_node) +{ + /* remove the input for parent node */ + + auto input_ir = base_node->inputs.begin(); + + while(input_ir != base_node->inputs.end()) + { + if(*input_ir == parent_node) + break; + + input_ir++; + } + + if(parent_node->inputs.size() == 1) + { + *input_ir = parent_node->inputs[0]; + } + else + { + base_node->inputs.erase(input_ir); + /* connect parent's input node and base node */ + + base_node->inputs.insert(base_node->inputs.end(), parent_node->inputs.begin(), parent_node->inputs.end()); + } + + /* setup the outputs of parent node's parent */ + + for(auto node : parent_node->inputs) + { + for(unsigned int i = 0; i < node->outputs.size(); i++) + { + if(node->outputs[i] == parent_node) + { + node->outputs[i] = base_node; + break; + } + } + } + + /* bridge parent's output, for those edges do not connect with base node */ + + auto output_ir = parent_node->outputs.begin(); + + while(output_ir != parent_node->outputs.end()) + { + TFNode* node = *output_ir; + + if(node != base_node) + { + base_node->outputs.push_back(node); + + for(unsigned int i = 0; i < node->inputs.size(); i++) + { + if(node->inputs[i] == parent_node) + { + node->inputs[i] = base_node; + break; + } + } + } + + output_ir++; + } + + /* handle TF definitions */ + + base_node->pb_defs.insert(base_node->pb_defs.end(), parent_node->pb_defs.begin(), parent_node->pb_defs.end()); + + // std::cout<<"base node: "<name<<" merge parent: "<name<<"\n"; + + parent_node->inputs.clear(); + parent_node->outputs.clear(); + + return 0; +} + +int CheckComposedBNAdd(TFNode* cur_node) +{ + if(cur_node->op != "Add") + return 0; + + TFNode* input0 = cur_node->inputs[0]; + TFNode* input1 = cur_node->inputs[1]; + + if(input0->op != "Mul" || input1->op != "Sub") + return 0; + + /* further check: /add_1 int name */ + if(cur_node->name.find("/add_1") != std::string::npos) + { + if(input0->name.find("/mul_1") != std::string::npos || input1->name.find("/mul_1") != std::string::npos) + cur_node->BNAddType = 1; + else + cur_node->BNAddType = 0; + + return 0; + } + + return -1; +} + +int BNRecursiveInputMerge(TFNode* node) +{ + bool mul_1_node = false; + bool mul_node = false; + if(node->name.find("/mul") != std::string::npos) + { + if(node->BNAddType == 1) + { + if(node->name.find("/mul_1") != std::string::npos) + { + mul_1_node = true; + } + else if(node->name.find("/mul_2") == std::string::npos) + { + // disconnect the connection between mul and mul2 + auto ir = node->outputs.begin(); + + if((*ir)->name.find("/mul2") == std::string::npos) + ir++; + + TFNode* mul2_node = *ir; + + node->outputs.erase(ir); + + ir = mul2_node->inputs.begin(); + + if((*ir)->name.find("/mul") == std::string::npos) + ir++; + + mul2_node->inputs.erase(ir); + } + } + else + { + if(node->name.find("/mul_1") != std::string::npos) + { + // disconnect the connection between add_1 mul_1 + auto ir = node->inputs.begin(); + + if((*ir)->name.find("/add_1") == std::string::npos) + ir++; + + if((*ir)->name.find("/add_1") != std::string::npos) + { + TFNode* Rsqrt_node = *ir; + + node->inputs.erase(ir); + + ir = Rsqrt_node->outputs.begin(); + + if((*ir)->name.find("/mul_1") == std::string::npos) + ir++; + + Rsqrt_node->outputs.erase(ir); + } + } + else + { + mul_node = true; + // printf("name:%s\n",node->name.c_str()); + } + } + } + + int orig_input_size = node->inputs.size(); + std::vector input_cpy = node->inputs; + + for(int i = 0; i < orig_input_size; i++) + { + if(mul_node && i == 0) + continue; + if(mul_1_node && i == 0) + continue; + + TFNode* input_node = input_cpy[i]; + input_node->BNAddType = node->BNAddType; + if(input_node->op == "Const") + continue; + + BNRecursiveInputMerge(input_node); + MergeParentNode(node, input_node); + } +} +int FuseComposedBN(TFNode* cur_node) +{ + BNRecursiveInputMerge(cur_node); + cur_node->op = "ComposedBN"; + + /* set new name */ + auto pos = cur_node->name.find("/add_1"); + cur_node->name.replace(pos, strlen("/add_1"), "bn.fused"); + + /* skip to create static node for add/y */ + + for(unsigned int i = 0; i < cur_node->inputs.size(); i++) + { + TFNode* node = cur_node->inputs[i]; + + if(node->name.find("/add/y") != std::string::npos) + node->no_static_node = true; + } +} +int MergeChildNode(TFNode* base_node, TFNode* child_node) +{ + auto output_ir = base_node->outputs.begin(); + + while(output_ir != base_node->outputs.end()) + { + if(*output_ir == child_node) + break; + output_ir++; + } + + if(child_node->outputs.size() == 1) + { + *output_ir = child_node->outputs[0]; + } + else + { + base_node->outputs.erase(output_ir); + base_node->outputs.insert(base_node->outputs.end(), child_node->outputs.begin(), child_node->outputs.end()); + } + + for(auto node : child_node->outputs) + { + for(unsigned int i = 0; i < node->inputs.size(); i++) + { + if(node->inputs[i] == child_node) + { + node->inputs[i] = base_node; + break; + } + } + } + + auto ir = child_node->inputs.begin(); + + while(ir != child_node->inputs.end()) + { + TFNode* node = *ir; + + if(node != base_node) + { + base_node->inputs.push_back(node); + + for(unsigned int i = 0; i < node->outputs.size(); i++) + { + if(node->outputs[i] == child_node) + { + node->outputs[i] = base_node; + break; + } + } + } + + ir++; + } + + base_node->pb_defs.insert(base_node->pb_defs.end(), child_node->pb_defs.begin(), child_node->pb_defs.end()); + + // std::cout<<"base node: "<name<<" merge child: "<name<<"\n"; + + child_node->inputs.clear(); + child_node->outputs.clear(); + + return 0; +} + + +void CleanupResizeNearestNeighbor(TFGraph& tf_graph) +{ + auto ir = tf_graph.seq_nodes.begin(); + + while(ir != tf_graph.seq_nodes.end()) + { + TFNode* cur_node = *ir; + + if(cur_node->op == "ResizeNearestNeighbor") + { + TFNode* data_node = cur_node->inputs[0]; + TFNode* data_shape_node = nullptr; + + for(unsigned int i = 0; i < data_node->outputs.size(); i++) + { + data_shape_node = data_node->outputs[i]; + + if(data_shape_node->op == "Shape") + break; + } + + DisconnectNode(data_shape_node); + + TFNode* mul_node = cur_node->inputs[1]; + TFNode* stride_slice = mul_node->inputs[0]; + DisconnectNode(stride_slice); + DisconnectNode(mul_node); + } + + ir++; + } +} + + +void tensorflow_serializer::MergeReluMinimum() +{ + for(auto ir = tf_graph.seq_nodes.begin(); ir != tf_graph.seq_nodes.end(); ir++) + { + TFNode* cur_node = *ir; + + if(cur_node->inputs.size() == 0) + continue; + + TFNode* input0 = cur_node->inputs[0]; + + if(cur_node->op == "Minimum" && input0->op == "Relu") + { + TFNode* const_node = cur_node->inputs[1]; + + DisconnectNode(const_node); + + MergeChildNode(input0, cur_node); + + input0->op = "Relu6"; + } + } +} + +int tensorflow_serializer::optimize_graph() +{ + /* first clean up the predictions module of TF */ + auto ir = tf_graph.seq_nodes.begin(); + + /* remove the squeeze node and identity */ + ir = tf_graph.seq_nodes.begin(); + + while(ir != tf_graph.seq_nodes.end()) + { + TFNode* cur_node = *ir; + + if(cur_node->op == "Squeeze") + { + TFNode* softmax_node = nullptr; + TFNode* shape_node = nullptr; + + for(unsigned int j = 0; j < cur_node->outputs.size(); j++) + { + if(cur_node->outputs[j]->op == "Softmax") + softmax_node = cur_node->outputs[j]; + else if(cur_node->outputs[j]->op == "Shape") + shape_node = cur_node->outputs[j]; + } + + if(softmax_node) + { + if(shape_node) + DisconnectNode(shape_node); + + TFNode* input_node = cur_node->inputs[0]; + MergeChildNode(input_node, cur_node); + ir = tf_graph.seq_nodes.erase(ir); + delete cur_node; + continue; + } + + if(cur_node->outputs.size() == 1 && softmax_node == nullptr) + { + TFNode* child_node = cur_node->outputs[0]; + + MergeParentNode(child_node, cur_node); + ir = tf_graph.seq_nodes.erase(ir); + delete cur_node; + continue; + } + } + + if(cur_node->op == "Identity") + { + TFNode* input_node = cur_node->inputs[0]; + MergeChildNode(input_node, cur_node); + + ir = tf_graph.seq_nodes.erase(ir); + delete cur_node; + continue; + } + + if(cur_node->op == "ConcatV2") + { + TFNode* axis_node = nullptr; + + for(unsigned int i = 0; i < cur_node->inputs.size(); i++) + { + TFNode* check_node = cur_node->inputs[i]; + + if(check_node->op == "Const") + { + axis_node = check_node; + break; + } + } + + if(axis_node) + { + cur_node->pb_defs.push_back(axis_node->pb_defs[0]); + DisconnectNode(axis_node); + } + } + + ir++; + } + + /* merge FIFOQueueV2 DequeueManyV2 */ + + ir = tf_graph.seq_nodes.begin(); + + while(ir != tf_graph.seq_nodes.end()) + { + TFNode* cur_node = *ir; + + if(cur_node->op == "FIFOQueueV2") + { + TFNode* queue_node = cur_node->outputs[0]; + + if(queue_node->op == "QueueDequeueManyV2") + { + MergeParentNode(queue_node, queue_node->inputs[1]); + } + + MergeChildNode(cur_node, queue_node); + + break; + } + + ir++; + } + + /* remove ExpandDims */ + ir = tf_graph.seq_nodes.begin(); + + while(ir != tf_graph.seq_nodes.end()) + { + TFNode* cur_node = *ir; + + if(cur_node->op == "ExpandDims") + { + TFNode* input0 = cur_node->inputs[0]; + TFNode* input1 = cur_node->inputs[1]; + + if(input0->op == "Constant" && input1->op == "Const") + { + TFNode* input1 = cur_node->inputs[1]; + TFNode* child_node = cur_node->outputs[0]; + + DisconnectNode(input1); + DisconnectNode(cur_node); + + child_node->inputs.push_back(input1); + input1->outputs.push_back(child_node); + } + else + { + if(input1->op == "Const") + DisconnectNode(input1); + else + DisconnectNode(input0); + + TFNode* child_node = cur_node->outputs[0]; + + MergeParentNode(child_node, cur_node); + } + + ir = tf_graph.seq_nodes.erase(ir); + delete cur_node; + + continue; + } + + ir++; + } + + /* merge biasadd and conv */ + ir = tf_graph.seq_nodes.begin(); + + while(ir != tf_graph.seq_nodes.end()) + { + TFNode* cur_node = *ir; + + if(cur_node->op == "Conv2D" || cur_node->op == "DepthwiseConv2dNative" || cur_node->op == "MatMul") + { + TFNode* output_node = cur_node->outputs[0]; + + if(output_node->op == "BiasAdd" || output_node->op == "Add") + { + MergeChildNode(cur_node, output_node); + } + } + + ir++; + } + + /* merge composed BatchNormal */ + + ir = tf_graph.seq_nodes.begin(); + + while(ir != tf_graph.seq_nodes.end()) + { + TFNode* cur_node = *ir; + + if(CheckComposedBNAdd(cur_node)) + FuseComposedBN(cur_node); + ir++; + } + + /* cleanup ResizeNearestNeighbor */ + CleanupResizeNearestNeighbor(tf_graph); + + /* merge Minimum and Relu */ + + MergeReluMinimum(); + /* merge input node and reshape */ + ir = tf_graph.seq_nodes.begin(); + while(ir != tf_graph.seq_nodes.end()) + { + TFNode* cur_node = *ir; + if(cur_node->op == "Reshape") + { + /* Reshape should have two inputs */ + TFNode* input_node0 = cur_node->inputs[0]; + TFNode* input_node1 = cur_node->inputs[1]; + + if(input_node0->op == "Placeholder" || input_node1->op == "Placeholder") + { + TFNode* input_node; + TFNode* const_node; + + if(input_node0->op == "Const") + { + const_node = input_node0; + input_node = input_node1; + } + else + { + const_node = input_node1; + input_node = input_node0; + } + + DisconnectNode(const_node); + MergeChildNode(input_node, cur_node); + input_node->pb_defs.insert(input_node->pb_defs.end(), const_node->pb_defs[0]); + + ir = tf_graph.seq_nodes.erase(ir); + delete cur_node; + break; + } + } + ir++; + } + + /* remove the shape and StrideSlice */ + + ir = tf_graph.seq_nodes.begin(); + + while(ir != tf_graph.seq_nodes.end()) + { + TFNode* cur_node = *ir; + if(cur_node->op == "StridedSlice") + { + /* check if input0 is "shape" */ + TFNode* input_node = cur_node->inputs[0]; + + if(input_node->op == "Shape") + { + /* here we go */ + DisconnectNode(cur_node); + DisconnectNode(input_node); + break; + } + } + + ir++; + } + + /* merge pad and conv */ + + ir = tf_graph.seq_nodes.begin(); + + while(ir != tf_graph.seq_nodes.end()) + { + TFNode* cur_node = *ir; + + if(cur_node->op == "Conv2D" || cur_node->op == "DepthwiseConv2dNative") + { + /* check if input is pad or not */ + TFNode* input_node = cur_node->inputs[0]; + + if(input_node->op == "Pad") + { + TFNode* padding_args = input_node->inputs[1]; + + input_node->pb_defs.push_back(padding_args->pb_defs[0]); + + DisconnectNode(padding_args); + MergeParentNode(cur_node, input_node); + + } + } + ir++; + } + + /*remove ArgMax node */ + + ir = tf_graph.seq_nodes.begin(); + while(ir != tf_graph.seq_nodes.end()) + { + TFNode* cur_node = *ir; + if(cur_node->op == "ArgMax") + { + DisconnectNode(cur_node); + tf_graph.seq_nodes.erase(ir); + + break; + } + + ir++; + } + + /* remove last squeeze */ + + ir = tf_graph.seq_nodes.begin(); + + while(ir != tf_graph.seq_nodes.end()) + { + TFNode* cur_node = *ir; + + if(cur_node->op == "Squeeze" && cur_node->outputs.empty()) + { + DisconnectNode(cur_node); + break; + } + ir++; + } + + /* remove no input and output nodes */ + + ir = tf_graph.seq_nodes.begin(); + + while(ir != tf_graph.seq_nodes.end()) + { + TFNode* cur_node = *ir; + + if(cur_node->inputs.size() == 0 && cur_node->outputs.size() == 0) + { + ir = tf_graph.seq_nodes.erase(ir); + delete cur_node; + } + else + ir++; + } + + /* remove no input but not placeholder/const nodes */ + ir = tf_graph.seq_nodes.begin(); + + while(ir != tf_graph.seq_nodes.end()) + { + TFNode* cur_node = *ir; + + if(cur_node->inputs.size() == 0 && cur_node->op != "Const" && cur_node->op != "Placeholder" && + cur_node->op != "FIFOQueueV2") + { + DisconnectNode(cur_node); + tf_graph.seq_nodes.erase(ir); + delete cur_node; + + ir = tf_graph.seq_nodes.begin(); // restart + } + else + ir++; + } + + return 0; +} + + +int tensorflow_serializer::FindRNNScope(std::string& rnn_scope) +{ + std::string rnn_node; + + std::string::size_type while_pos; + + int rnn_type = -1; + + for(unsigned int i = 0; i < tf_graph.seq_nodes.size(); i++) + { + TFNode* node = tf_graph.seq_nodes.at(i); + std::string& name = node->name; + + while_pos = name.find("while"); + + if(while_pos == std::string::npos) + continue; + + std::string::size_type cell_pos = name.find("lstm_cell", while_pos); + + if(cell_pos != std::string::npos) + { + rnn_node = node->name; + rnn_type = TF_RNN_LSTM; + break; + } + + cell_pos = name.find("gru_cell", while_pos); + + if(cell_pos != std::string::npos) + { + rnn_node = node->name; + rnn_type = TF_RNN_GRU; + break; + } + + cell_pos = name.find("basic_lstm_cell", while_pos); + + if(cell_pos != std::string::npos) + { + rnn_node = node->name; + rnn_type = TF_RNN_BASIC_LSTM; + break; + } + + cell_pos = name.find("basic_rnn_cell", while_pos); + + if(cell_pos != std::string::npos) + { + rnn_node = node->name; + rnn_type = TF_RNN_BASIC_RNN; + break; + } + } + + if(rnn_node.empty()) + return -1; + + std::string rnn_layer = rnn_node.substr(0, while_pos - 1); + std::string::size_type up_pos = rnn_layer.rfind("/"); + + rnn_scope = rnn_layer.substr(0, up_pos + 1); + + return rnn_type; +} + +void tensorflow_serializer::ParseLSTMGraph(LSTMNode* lstm_node, std::set& rnn_graph) +{ + /* parse input node */ + + for(unsigned int i = 0; i < lstm_node->inputs.size(); i++) + { + TFNode* node = lstm_node->inputs[i]; + + if(node->op != "Const") + continue; + + // node->no_static_node=true; //do not automatically create Static Node + + if(node->name.find("lstm_cell/kernel") != std::string::npos) + { + lstm_node->kernel = node; + } + else if(node->name.find("lstm_cell/bias") != std::string::npos) + { + lstm_node->bias = node; + } + else if(node->name.find("lstm_cell/w_f_diag") != std::string::npos) + { + lstm_node->w_f_diag = node; + } + else if(node->name.find("lstm_cell/w_o_diag") != std::string::npos) + { + lstm_node->w_o_diag = node; + } + else if(node->name.find("lstm_cell/w_i_diag") != std::string::npos) + { + lstm_node->w_i_diag = node; + } + else if(node->name.find("lstm_cell/projection/kernel") != std::string::npos) + { + lstm_node->projection = node; + } + } + + auto rnn_ir = rnn_graph.begin(); + auto rnn_ir_end = rnn_graph.end(); + + while(rnn_ir != rnn_ir_end) + { + TFNode* node = *rnn_ir; + int name_len = node->name.size(); + std::string zero_name = "LSTMCellZeroState/zeros"; + std::string zero1_name = "LSTMCellZeroState/zeros_1"; + std::string forget_name = "lstm_cell/add/y"; + + if(node->name.find(zero_name, name_len - zero_name.size()) != std::string::npos) + lstm_node->init_c = node; + else if(node->name.find(zero1_name, name_len - zero1_name.size()) != std::string::npos) + lstm_node->init_h = node; + else if(node->name.find(forget_name, name_len - forget_name.size()) != std::string::npos) + lstm_node->forget_bias = node; + + rnn_ir++; + } +} +void ParseGRUGraph(TFGraph& tf_graph, GRUNode* gru_node, std::set& rnn_graph) +{ + /* parse input node */ + + for(unsigned int i = 0; i < gru_node->inputs.size(); i++) + { + TFNode* node = gru_node->inputs[i]; + + if(node->op != "Const") + continue; + + // node->no_static_node=true; //do not automatically create Static Node + + if(node->name.find("gru_cell/gates/kernel") != std::string::npos) + { + gru_node->gate_kernel = node; + } + else if(node->name.find("gru_cell/gates/bias") != std::string::npos) + { + gru_node->gate_bias = node; + } + else if(node->name.find("gru_cell/candidate/kernel") != std::string::npos) + { + gru_node->candidate_kernel = node; + } + else if(node->name.find("gru_cell/candidate/bias") != std::string::npos) + { + gru_node->candidate_bias = node; + } + } + + auto rnn_ir = rnn_graph.begin(); + auto rnn_ir_end = rnn_graph.end(); + + while(rnn_ir != rnn_ir_end) + { + TFNode* node = *rnn_ir; + int name_len = node->name.size(); + std::string zero_name = "GRUCellZeroState/zeros"; + + if(node->name.find(zero_name, name_len - zero_name.size()) != std::string::npos) + gru_node->init_h = node; + + rnn_ir++; + } +} +void ParseRNNGraph(TFGraph& tf_graph, RNNNode* rnn_node, std::set& rnn_graph) +{ + /* parse input node */ + + for(unsigned int i = 0; i < rnn_node->inputs.size(); i++) + { + TFNode* node = rnn_node->inputs[i]; + + if(node->op != "Const") + continue; + + // node->no_static_node=true; //do not automatically create Static Node + + if(node->name.find("basic_rnn_cell/kernel") != std::string::npos) + { + rnn_node->kernel = node; + } + else if(node->name.find("basic_rnn_cell/bias") != std::string::npos) + { + rnn_node->bias = node; + } + } + + auto rnn_ir = rnn_graph.begin(); + auto rnn_ir_end = rnn_graph.end(); + + while(rnn_ir != rnn_ir_end) + { + TFNode* node = *rnn_ir; + int name_len = node->name.size(); + std::string zero_name = "BasicRNNCellZeroState/zeros"; + + if(node->name.find(zero_name, name_len - zero_name.size()) != std::string::npos) + rnn_node->init_h = node; + + rnn_ir++; + } +} +void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) +{ + // collect attributes according to rnn_type + + if(rnn_type == TF_RNN_LSTM) + { + LSTMNode* lstm_node = new LSTMNode(); + + lstm_node->name = rnn_scope + "lstm"; + lstm_node->op = "LSTM"; + + std::set& rnn_graph = lstm_node->rnn_graph; + + std::set rnn_inputs; + std::set rnn_outputs; + + auto ir = tf_graph.seq_nodes.begin(); + std::string::size_type prefix_len = rnn_scope.size(); + + while(ir != tf_graph.seq_nodes.end()) + { + TFNode* node = *ir; + + if(node->name.find(rnn_scope.c_str(), 0, prefix_len) == std::string::npos) + { + ir++; + continue; + } + + /* this is a node, inside rnn scope, remove it from graph first */ + ir = tf_graph.seq_nodes.erase(ir); + + rnn_graph.insert(node); + } + + auto rnn_ir = rnn_graph.begin(); + auto rnn_end = rnn_graph.end(); + + while(rnn_ir != rnn_end) + { + TFNode* node = *rnn_ir; + + for(unsigned int i = 0; i < node->inputs.size(); i++) + { + TFNode* input = node->inputs[i]; + + if(!rnn_graph.count(input)) + rnn_inputs.insert(input); + } + + for(unsigned int i = 0; i < node->outputs.size(); i++) + { + TFNode* output = node->outputs[i]; + + if(!rnn_graph.count(output)) + rnn_outputs.insert(output); + } + + rnn_ir++; + } + + // insert lstm node + auto seq_ir = tf_graph.seq_nodes.begin(); + + while(seq_ir != tf_graph.seq_nodes.end()) + { + TFNode* node = *seq_ir; + + if(rnn_inputs.count(node)) + { + tf_graph.seq_nodes.insert(seq_ir, lstm_node); + break; + } + + seq_ir++; + } + + // connect inputs and outputs + auto set_ir = rnn_inputs.begin(); + auto set_ir_end = rnn_inputs.end(); + + while(set_ir != set_ir_end) + { + TFNode* input_node = *set_ir; + + for(unsigned int j = 0; j < input_node->outputs.size(); j++) + { + TFNode* child_node = input_node->outputs[j]; + + if(rnn_graph.count(child_node)) + input_node->outputs[j] = lstm_node; + } + + lstm_node->inputs.push_back(input_node); + + if(input_node->op == "Identity") + { + TFNode* parent_node = input_node->inputs[0]; + + MergeChildNode(parent_node, input_node); + } + + set_ir++; + } + + set_ir = rnn_outputs.begin(); + set_ir_end = rnn_outputs.end(); + + while(set_ir != set_ir_end) + { + TFNode* output_node = *set_ir; + + for(unsigned int j = 0; j < output_node->inputs.size(); j++) + { + TFNode* parent_node = output_node->inputs[j]; + + if(rnn_graph.count(parent_node)) + output_node->inputs[j] = lstm_node; + } + + lstm_node->outputs.push_back(output_node); + set_ir++; + } + + /* sort input node and output node according to index */ + std::sort(lstm_node->inputs.begin(), lstm_node->inputs.end(), + [](const TFNode* a, const TFNode* b) { return a->idx < b->idx; }); + + std::sort(lstm_node->outputs.begin(), lstm_node->outputs.end(), + [](const TFNode* a, const TFNode* b) { return a->idx < b->idx; }); + + ParseLSTMGraph(lstm_node, rnn_graph); + } + + if(rnn_type == TF_RNN_BASIC_RNN) + { + RNNNode* rnn_node = new RNNNode(); + + rnn_node->name = rnn_scope + "rnn"; + // std::cout<op = "RNN"; + + std::set& rnn_graph = rnn_node->rnn_graph; + + std::set rnn_inputs; + std::set rnn_outputs; + + auto ir = tf_graph.seq_nodes.begin(); + std::string::size_type prefix_len = rnn_scope.size(); + + while(ir != tf_graph.seq_nodes.end()) + { + TFNode* node = *ir; + + if(node->name.find(rnn_scope.c_str(), 0, prefix_len) == std::string::npos) + { + ir++; + continue; + } + + /* this is a node, inside rnn scope, remove it from graph first */ + ir = tf_graph.seq_nodes.erase(ir); + + rnn_graph.insert(node); + } + + auto rnn_ir = rnn_graph.begin(); + auto rnn_end = rnn_graph.end(); + + while(rnn_ir != rnn_end) + { + TFNode* node = *rnn_ir; + + for(unsigned int i = 0; i < node->inputs.size(); i++) + { + TFNode* input = node->inputs[i]; + + if(!rnn_graph.count(input)) + rnn_inputs.insert(input); + } + + for(unsigned int i = 0; i < node->outputs.size(); i++) + { + TFNode* output = node->outputs[i]; + + if(!rnn_graph.count(output)) + rnn_outputs.insert(output); + } + + rnn_ir++; + } + + // insert rnn node + auto seq_ir = tf_graph.seq_nodes.begin(); + + while(seq_ir != tf_graph.seq_nodes.end()) + { + TFNode* node = *seq_ir; + + if(rnn_inputs.count(node)) + { + tf_graph.seq_nodes.insert(seq_ir, rnn_node); + break; + } + + seq_ir++; + } + + // connect inputs and outputs + auto set_ir = rnn_inputs.begin(); + auto set_ir_end = rnn_inputs.end(); + + while(set_ir != set_ir_end) + { + TFNode* input_node = *set_ir; + + for(unsigned int j = 0; j < input_node->outputs.size(); j++) + { + TFNode* child_node = input_node->outputs[j]; + + if(rnn_graph.count(child_node)) + input_node->outputs[j] = rnn_node; + } + + rnn_node->inputs.push_back(input_node); + + if(input_node->op == "Identity") + { + TFNode* parent_node = input_node->inputs[0]; + + MergeChildNode(parent_node, input_node); + } + + set_ir++; + } + + set_ir = rnn_outputs.begin(); + set_ir_end = rnn_outputs.end(); + + while(set_ir != set_ir_end) + { + TFNode* output_node = *set_ir; + + for(unsigned int j = 0; j < output_node->inputs.size(); j++) + { + TFNode* parent_node = output_node->inputs[j]; + + if(rnn_graph.count(parent_node)) + output_node->inputs[j] = rnn_node; + } + + rnn_node->outputs.push_back(output_node); + set_ir++; + } + + /* sort input node and output node according to index */ + std::sort(rnn_node->inputs.begin(), rnn_node->inputs.end(), + [](const TFNode* a, const TFNode* b) { return a->idx < b->idx; }); + + std::sort(rnn_node->outputs.begin(), rnn_node->outputs.end(), + [](const TFNode* a, const TFNode* b) { return a->idx < b->idx; }); + + ParseRNNGraph(tf_graph, rnn_node, rnn_graph); + } + if(rnn_type == TF_RNN_GRU) + { + GRUNode* gru_node = new GRUNode(); + + gru_node->name = rnn_scope + "gru"; + // std::cout<op = "GRU"; + + std::set& rnn_graph = gru_node->rnn_graph; + + std::set rnn_inputs; + std::set rnn_outputs; + + auto ir = tf_graph.seq_nodes.begin(); + std::string::size_type prefix_len = rnn_scope.size(); + + while(ir != tf_graph.seq_nodes.end()) + { + TFNode* node = *ir; + + if(node->name.find(rnn_scope.c_str(), 0, prefix_len) == std::string::npos) + { + ir++; + continue; + } + + /* this is a node, inside rnn scope, remove it from graph first */ + ir = tf_graph.seq_nodes.erase(ir); + + rnn_graph.insert(node); + } + + auto rnn_ir = rnn_graph.begin(); + auto rnn_end = rnn_graph.end(); + + while(rnn_ir != rnn_end) + { + TFNode* node = *rnn_ir; + + for(unsigned int i = 0; i < node->inputs.size(); i++) + { + TFNode* input = node->inputs[i]; + + if(!rnn_graph.count(input)) + rnn_inputs.insert(input); + } + + for(unsigned int i = 0; i < node->outputs.size(); i++) + { + TFNode* output = node->outputs[i]; + + if(!rnn_graph.count(output)) + rnn_outputs.insert(output); + } + + rnn_ir++; + } + + // insert rnn node + auto seq_ir = tf_graph.seq_nodes.begin(); + + while(seq_ir != tf_graph.seq_nodes.end()) + { + TFNode* node = *seq_ir; + + if(rnn_inputs.count(node)) + { + tf_graph.seq_nodes.insert(seq_ir, gru_node); + break; + } + + seq_ir++; + } + + // connect inputs and outputs + auto set_ir = rnn_inputs.begin(); + auto set_ir_end = rnn_inputs.end(); + + while(set_ir != set_ir_end) + { + TFNode* input_node = *set_ir; + + for(unsigned int j = 0; j < input_node->outputs.size(); j++) + { + TFNode* child_node = input_node->outputs[j]; + + if(rnn_graph.count(child_node)) + input_node->outputs[j] = gru_node; + } + + gru_node->inputs.push_back(input_node); + + if(input_node->op == "Identity") + { + TFNode* parent_node = input_node->inputs[0]; + + MergeChildNode(parent_node, input_node); + } + + set_ir++; + } + + set_ir = rnn_outputs.begin(); + set_ir_end = rnn_outputs.end(); + + while(set_ir != set_ir_end) + { + TFNode* output_node = *set_ir; + + for(unsigned int j = 0; j < output_node->inputs.size(); j++) + { + TFNode* parent_node = output_node->inputs[j]; + + if(rnn_graph.count(parent_node)) + output_node->inputs[j] = gru_node; + } + + gru_node->outputs.push_back(output_node); + set_ir++; + } + + /* sort input node and output node according to index */ + std::sort(gru_node->inputs.begin(), gru_node->inputs.end(), + [](const TFNode* a, const TFNode* b) { return a->idx < b->idx; }); + + std::sort(gru_node->outputs.begin(), gru_node->outputs.end(), + [](const TFNode* a, const TFNode* b) { return a->idx < b->idx; }); + + ParseGRUGraph(tf_graph, gru_node, rnn_graph); + } + + // cleanup zero in/zero out node + auto seq_ir = tf_graph.seq_nodes.begin(); + + while(seq_ir != tf_graph.seq_nodes.end()) + { + TFNode* node = *seq_ir; + + if(node->inputs.size() == 0 && node->outputs.size() == 0) + { + delete node; + seq_ir = tf_graph.seq_nodes.erase(seq_ir); + } + else + { + seq_ir++; + } + } +} +int tensorflow_serializer::optimize_rnn() +{ + while(1) + { + std::string rnn_scope; + + int rnn_type = FindRNNScope(rnn_scope); + + if(rnn_scope.empty()) + break; + + StripRNNScope(rnn_scope, rnn_type); + } + + return true; +} + + +int tensorflow_serializer::generate_graph(ir_graph_t* graph) +{ + int node_number = tf_graph.seq_nodes.size(); + int i; + + bool debug_graph = false; + const char* debug_env = std::getenv("DEBUG_TF"); + if((debug_env) && (debug_env[0] == '1')) + { + debug_graph = true; + } + + printf("node_number: %d \n", node_number); + // first: create all tensor node + for(i = 0; i < node_number; i++) + { + TFNode* tf_node = tf_graph.seq_nodes[i]; + + if(debug_graph) + { + std::cout << i << "\t" << tf_node->op << "\t" << tf_node->name << "\n"; + } + + if(tf_node->no_static_node) + continue; + + if(tf_node->op == "Const") + { + load_const_tensor(tf_node, graph); + continue; + } + + + // StaticNode* node = CreateStaticNode(graph, tf_node->name); + // std::string& op_name = tf_node->op; + ir_node_t* ir_node = create_ir_node(graph,tf_node->name.c_str(), op_load_map[tf_node->op].first, OP_VERSION); + /* create tensor */ + ir_tensor_t* ir_tensor = create_ir_tensor(graph, tf_node->name.c_str(), TENGINE_DT_FP32); + + set_ir_node_output_tensor(ir_node, 0, ir_tensor); + tf_node->ir_node = ir_node; + tf_node->ir_tensor = ir_tensor; + } + + std::vector no_supported_op; + for(i = 0; i < node_number; i++) + { + TFNode* tf_node = tf_graph.seq_nodes[i]; + + if(tf_node->op == "Placeholder" || tf_node->op == "Const") + continue; + + // if(!FindOpLoadMethod(tf_node->op)) + // { + // auto it = find(no_supported_op.begin(),no_supported_op.end(),tf_node->op); + // if(it != no_supported_op.end()) + // no_supported_op.push_back(tf_node->op); + // } + } + if(no_supported_op.size()) + { + TLOG_ERR("These ops are not supported \n", no_supported_op.size()); + TLOG_ERR("{"); + for(int j = 0; j < (int)no_supported_op.size(); j++) + { + TLOG_ERR("%d ", no_supported_op[j] ); + } + TLOG_ERR("}\n"); + return false; + } +// for(int i = 0; i < node_number; i++){ +// TFNode* tf_node = tf_graph.seq_nodes[i]; +// if(tf_node->op == "null" || tf_node->op == "Placeholder" || tf_node->op == "Const") +// continue; + +// std::vector::iterator iter=std::find(support_op.begin(), support_op.end(), tf_node->op); +// if(iter==support_op.end()){ +// std::vector::iterator uniter=std::find(unsupport_op.begin(), unsupport_op.end(), tf_node->op); +// if(uniter==unsupport_op.end()){ +// unsupport_op.push_back(tf_node->op); +// } else { +// continue; +// } +// } else { +// continue; +// } +// } +// if(unsupport_op.size() != 0){ +// printf("These ops are not in tensorflow serializer: \n"); +// for(int i = 0; i < (int)unsupport_op.size(); i++){ +// printf("[ %s ]\n", unsupport_op[i].c_str()); +// } +// printf("\n"); +// return false; +// } + for(i = 0; i < node_number; i++) + { + TFNode* tf_node = tf_graph.seq_nodes[i]; + + if(tf_node->op == "Placeholder" || tf_node->op == "Const") + continue; + + + op_load_t loader = op_load_map[tf_node->op].second; + if (loader(graph, tf_node->ir_node, tf_node) < 0) + { + fprintf(stderr, "load op %s func failed in node %s .\n", tf_node->op.c_str(), tf_node->name.c_str()); + return -1; + } + + // op_load_t loader = op_load_map[caffe_op_name].second; + // if (loader(graph, ir_node, layer_param) < 0) + // { + // TLOG_ERR("load op %s func failed in node %s .\n", caffe_op_name.c_str(), ir_node->name); + // return -1; + // } + } + + if(i < node_number) + return false; + + return true; +} +int tensorflow_serializer::load_graph(ir_graph_t* graph) +{ + printf("tf_net node num : %d \n", tf_net.node_size()); + if (construct_graph() < 0) + return -1; + + if(optimize_rnn() < 0) + return false; + + if (optimize_graph() < 0) + return -1; + + if (set_graph_input(graph) < 0) + return -1; + + if(generate_graph(graph) < 0) + return -1; + + return 0; +} + + +int tensorflow_serializer::load_model(ir_graph_t* graph, std::string model_file) +{ + register_op_load(); + if (load_binary_file(model_file) < 0) + return -1; + fprintf(stderr, "Process 1: Finish load protobuf file \n"); + // if (load_tensor_data(graph, test_net, train_net) < 0) + // return -1; + // fprintf(stderr, "Process 2: Finish load graph node \n"); + + load_graph(graph); + // fprintf(stderr, "Process 3: Finish set graph input \n"); + // if (load_graph_node(graph, test_net, train_net) < 0) + // return -1; + // fprintf(stderr, "Process 4: Finish load graph node \n"); + // if (set_graph_output(graph, test_net, train_net) < 0) + // return -1; + // fprintf(stderr, "Process 5: Finish set graph output \n"); + return 0; +} + +graph_t tensorflow_serializer::tensorflow2tengine(std::string model_file) +{ + fprintf(stderr, "----------tensorflow2tengine begin----------\n"); + + context_t context = create_context(NULL, 1); + ir_graph_t* ir_graph = create_ir_graph((struct context*)context); + if (ir_graph == NULL) + { + destroy_context(context); + return NULL; + } + ir_graph->attribute->private_context = 1; // new context + + int ret = load_model(ir_graph, model_file); + if (0 != ret) + { + destroy_graph(ir_graph); + return NULL; + } + ir_graph->device = find_default_device(); + + fprintf(stderr, "----------tensorflow2tengine done.----------\n"); + return ir_graph; +} + +void tensorflow_serializer::register_op_load() +{ + +} \ No newline at end of file diff --git a/tools/convert_tool/tensorflow/tf2tengine.hpp b/tools/convert_tool/tensorflow/tf2tengine.hpp new file mode 100644 index 000000000..e23e9a80f --- /dev/null +++ b/tools/convert_tool/tensorflow/tf2tengine.hpp @@ -0,0 +1,248 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * License); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* + * Copyright (c) 2021, OPEN AI LAB + * Author: bzhang@openailab.com + */ + +#ifndef __TENSORFLOW2TENGINE_HPP__ +#define __TENSORFLOW2TENGINE_HPP__ + +#include +#include +#include +#include +#include +#include +#include + +#include "graph.pb.h" + +#include +#include +#include +#include +#include + +extern "C" { +#include "tengine/c_api.h" +#include "graph/graph.h" +#include "graph/subgraph.h" +#include "graph/node.h" +#include "graph/tensor.h" +#include "executer/executer.h" +#include "module/module.h" +#include "utility/log.h" +#include "utility/sys_port.h" +#include "utility/vector.h" +#include "save_graph/op_include.h" +} + + +#define TF_RNN_LSTM 0 +#define TF_RNN_GRU 1 +#define TF_RNN_BASIC_LSTM 2 +#define TF_RNN_BASIC_RNN 3 + + +struct TFNode +{ + int idx; + std::string name; + std::string op; + std::vector inputs; + std::vector outputs; + std::vector pb_defs; + ir_node_t* ir_node; + ir_tensor_t* ir_tensor; + bool no_static_node; + int BNAddType; + + TFNode() + { + no_static_node = false; + } + + virtual ~TFNode() {} +}; + +struct LSTMNode : public TFNode +{ + float clip; + + std::string direction; + + /* optional inputs */ + TFNode* kernel; + TFNode* bias; + TFNode* w_f_diag; + TFNode* w_i_diag; + TFNode* w_o_diag; + TFNode* projection; + TFNode* init_h; + TFNode* init_c; + TFNode* forget_bias; + + std::set rnn_graph; + + LSTMNode() + { + kernel = nullptr; + bias = nullptr; + w_f_diag = nullptr; + w_i_diag = nullptr; + w_o_diag = nullptr; + projection = nullptr; + init_h = nullptr; + init_c = nullptr; + forget_bias = nullptr; + } + + ~LSTMNode() + { + auto rnn_ir = rnn_graph.begin(); + auto rnn_end = rnn_graph.end(); + + while(rnn_ir != rnn_end) + { + delete(*rnn_ir); + rnn_ir++; + } + } +}; + +struct RNNNode : public TFNode +{ + float clip; + + std::string direction; + + /* optional inputs */ + TFNode* kernel; + TFNode* bias; + TFNode* init_h; + + std::set rnn_graph; + + RNNNode() + { + kernel = nullptr; + bias = nullptr; + init_h = nullptr; + } + + ~RNNNode() + { + auto rnn_ir = rnn_graph.begin(); + auto rnn_end = rnn_graph.end(); + + while(rnn_ir != rnn_end) + { + delete(*rnn_ir); + rnn_ir++; + } + } +}; + +struct GRUNode : public TFNode +{ + float clip; + + std::string direction; + + /* optional inputs */ + TFNode* kernel; + TFNode* bias; + TFNode* init_h; + // gru kernel & bias + TFNode* gate_kernel; + TFNode* gate_bias; + TFNode* candidate_kernel; + TFNode* candidate_bias; + + std::set rnn_graph; + + GRUNode() + { + kernel = nullptr; + bias = nullptr; + init_h = nullptr; + gate_kernel = nullptr; + gate_bias = nullptr; + candidate_kernel = nullptr; + candidate_bias = nullptr; + } + + ~GRUNode() + { + auto rnn_ir = rnn_graph.begin(); + auto rnn_end = rnn_graph.end(); + + while(rnn_ir != rnn_end) + { + delete(*rnn_ir); + rnn_ir++; + } + } +}; + +struct TFGraph +{ + std::vector seq_nodes; + + ~TFGraph() + { + for(auto node : seq_nodes) + delete node; + } +}; + + +class tensorflow_serializer +{ +public: + graph_t tensorflow2tengine(std::string model_file); + typedef int (*op_load_t)(ir_graph_t* graph, ir_node_t* node,TFNode* tf_node); + +private: + std::unordered_map > op_load_map; + int load_graph(ir_graph_t* graph); + int load_model(ir_graph_t* graph, std::string model_file); + int load_binary_file(std::string model_file); + int load_graph_node(tensorflow::GraphDef& tf_net, ir_graph_t* graph); + int load_tensor_data(TFNode* tf_node, ir_graph_t* graph); + int optimize_graph(); + int set_graph_input(ir_graph_t* graph); + int set_graph_output(ir_graph_t* graph); + bool find_op_load_method(const std::string& op_name); + int generate_graph(ir_graph_t* graph); + int construct_graph(); + ir_tensor_t* find_tensor(ir_graph_t* graph, const std::string& tensor_name); + void register_op_load(); + int FindRNNScope(std::string& rnn_scope); + void ParseLSTMGraph(LSTMNode* lstm_node, std::set& rnn_graph); + void StripRNNScope(std::string& rnn_scope, int rnn_type); + void MergeReluMinimum(); + int optimize_rnn(); + tensorflow::GraphDef tf_net; + TFGraph tf_graph; +}; + +#endif \ No newline at end of file diff --git a/tools/convert_tool/tensorflow/types.proto b/tools/convert_tool/tensorflow/types.proto new file mode 100644 index 000000000..1beb2a1aa --- /dev/null +++ b/tools/convert_tool/tensorflow/types.proto @@ -0,0 +1,66 @@ +syntax = "proto3"; + +package tensorflow; +option cc_enable_arenas = true; +option java_outer_classname = "TypesProtos"; +option java_multiple_files = true; +option java_package = "org.tensorflow.framework"; + +// LINT.IfChange +enum DataType { + // Not a legal value for DataType. Used to indicate a DataType field + // has not been set. + DT_INVALID = 0; + + // Data types that all computation devices are expected to be + // capable to support. + DT_FLOAT = 1; + DT_DOUBLE = 2; + DT_INT32 = 3; + DT_UINT8 = 4; + DT_INT16 = 5; + DT_INT8 = 6; + DT_STRING = 7; + DT_COMPLEX64 = 8; // Single-precision complex + DT_INT64 = 9; + DT_BOOL = 10; + DT_QINT8 = 11; // Quantized int8 + DT_QUINT8 = 12; // Quantized uint8 + DT_QINT32 = 13; // Quantized int32 + DT_BFLOAT16 = 14; // Float32 truncated to 16 bits. Only for cast ops. + DT_QINT16 = 15; // Quantized int16 + DT_QUINT16 = 16; // Quantized uint16 + DT_UINT16 = 17; + DT_COMPLEX128 = 18; // Double-precision complex + DT_HALF = 19; + DT_RESOURCE = 20; + DT_VARIANT = 21; // Arbitrary C++ data types + + // TODO(josh11b): DT_GENERIC_PROTO = ??; + // TODO(jeff,josh11b): DT_UINT64? DT_UINT32? + + // Do not use! These are only for parameters. Every enum above + // should have a corresponding value below (verified by types_test). + DT_FLOAT_REF = 101; + DT_DOUBLE_REF = 102; + DT_INT32_REF = 103; + DT_UINT8_REF = 104; + DT_INT16_REF = 105; + DT_INT8_REF = 106; + DT_STRING_REF = 107; + DT_COMPLEX64_REF = 108; + DT_INT64_REF = 109; + DT_BOOL_REF = 110; + DT_QINT8_REF = 111; + DT_QUINT8_REF = 112; + DT_QINT32_REF = 113; + DT_BFLOAT16_REF = 114; + DT_QINT16_REF = 115; + DT_QUINT16_REF = 116; + DT_UINT16_REF = 117; + DT_COMPLEX128_REF = 118; + DT_HALF_REF = 119; + DT_RESOURCE_REF = 120; + DT_VARIANT_REF = 121; +} +// LINT.ThenChange(https://www.tensorflow.org/code/tensorflow/c/c_api.h,https://www.tensorflow.org/code/tensorflow/go/tensor.go) diff --git a/tools/convert_tool/tensorflow/versions.proto b/tools/convert_tool/tensorflow/versions.proto new file mode 100644 index 000000000..7d5e58ae7 --- /dev/null +++ b/tools/convert_tool/tensorflow/versions.proto @@ -0,0 +1,31 @@ +syntax = "proto3"; + +package tensorflow; +option cc_enable_arenas = true; +option java_outer_classname = "VersionsProtos"; +option java_multiple_files = true; +option java_package = "org.tensorflow.framework"; + +// Version information for a piece of serialized data +// +// There are different types of versions for each type of data +// (GraphDef, etc.), but they all have the same common shape +// described here. +// +// Each consumer has "consumer" and "min_producer" versions (specified +// elsewhere). A consumer is allowed to consume this data if +// +// producer >= min_producer +// consumer >= min_consumer +// consumer not in bad_consumers +// +message VersionDef { + // The version of the code that produced this data. + int32 producer = 1; + + // Any consumer below this version is not allowed to consume this data. + int32 min_consumer = 2; + + // Specific consumer versions which are disallowed (e.g. due to bugs). + repeated int32 bad_consumers = 3; +}; From e7d6f33bc34094f8b0888a28939f1997d489d668 Mon Sep 17 00:00:00 2001 From: bzhang Date: Thu, 19 Aug 2021 15:50:16 +0800 Subject: [PATCH 2/8] tf serializer version 1 --- tools/convert_tool/tensorflow/tf2tengine.cpp | 611 +++++++++++++++---- tools/convert_tool/tensorflow/tf2tengine.hpp | 9 +- 2 files changed, 490 insertions(+), 130 deletions(-) diff --git a/tools/convert_tool/tensorflow/tf2tengine.cpp b/tools/convert_tool/tensorflow/tf2tengine.cpp index 50560ef6e..d925e731c 100644 --- a/tools/convert_tool/tensorflow/tf2tengine.cpp +++ b/tools/convert_tool/tensorflow/tf2tengine.cpp @@ -62,18 +62,22 @@ static bool GetAttrValue(const tensorflow::NodeDef* node, const char* key, tenso return false; } -static void GetTensorContentAndDim(const tensorflow::TensorProto& tf_tensor, int* dims, void** mem_ptr, - std::string& layout, int dim_num) +int GetTensorContentAndDim(const tensorflow::TensorProto& tf_tensor, int** dims, void** mem_ptr, + std::string& layout) { const tensorflow::TensorShapeProto& shape = tf_tensor.tensor_shape(); int elem_num = 1; - dim_num = shape.dim_size(); + int dim_num = shape.dim_size(); + int* dim_tmp = (int*)malloc(sizeof(int)*dim_num); + + // printf("dim num : %d \n", dim_num); + // dims = (int*)malloc(sizeof(int)*dim_num); for(int i = 0; i < dim_num; i++) { elem_num *= shape.dim(i).size(); - dims[i] = shape.dim(i).size(); + dim_tmp[i] = shape.dim(i).size(); } void* mem_buf = nullptr; @@ -81,7 +85,6 @@ static void GetTensorContentAndDim(const tensorflow::TensorProto& tf_tensor, int if(tf_tensor.tensor_content().size()) { int content_size = tf_tensor.tensor_content().size(); - mem_buf = malloc(content_size + 128); void* src = ( void* )tf_tensor.tensor_content().c_str(); memcpy(mem_buf, src, content_size); @@ -92,7 +95,6 @@ static void GetTensorContentAndDim(const tensorflow::TensorProto& tf_tensor, int int data_num = tf_tensor.float_val_size(); mem_buf = malloc(elem_num * sizeof(float)); float* mem = ( float* )mem_buf; - if(data_num >= elem_num) { for(int i = 0; i < elem_num; i++) @@ -145,7 +147,7 @@ static void GetTensorContentAndDim(const tensorflow::TensorProto& tf_tensor, int } *mem_ptr = mem_buf; - + *dims = dim_tmp; switch(dim_num) { case 0: @@ -163,6 +165,7 @@ static void GetTensorContentAndDim(const tensorflow::TensorProto& tf_tensor, int default: break; } + return dim_num; } int tensorflow_serializer::load_binary_file(std::string model_file) { @@ -191,7 +194,6 @@ int tensorflow_serializer::load_binary_file(std::string model_file) TLOG_ERR( "parse file: %s failed\n",model_file.c_str()); return -1; } - printf("graphd node numebr : %d \n", tf_net.node_size()); return ret; } int load_const_tensor(TFNode* tf_node, ir_graph_t* graph) @@ -199,24 +201,28 @@ int load_const_tensor(TFNode* tf_node, ir_graph_t* graph) ir_node_t* node = create_ir_node(graph, tf_node->name.c_str(), OP_CONST, OP_VERSION); ir_tensor_t* tensor = create_ir_tensor(graph, tf_node->name.c_str(),TENGINE_DT_FP32); tensorflow::AttrValue value; - const tensorflow::NodeDef* node_def = tf_node->pb_defs[0]; if(GetAttrValue(node_def, "value", value)) { const tensorflow::TensorProto& tf_tensor = value.tensor(); void* mem_ptr; int* dims ; - int dim_num; std::string layout; - GetTensorContentAndDim(tf_tensor, dims, &mem_ptr, layout, dim_num); - int mem_size = sizeof(float); - for(unsigned int i = 0; i < dim_num; i++) - { - mem_size *= dims[i]; - } + int dim_num = GetTensorContentAndDim(tf_tensor, &dims, &mem_ptr, layout); set_ir_tensor_shape(tensor, dims, dim_num); - // SetTensorDim(tensor, dims, dims.size()); + int mem_size = 1; + for(int i = 0; i < dim_num; i++) + mem_size *= dims[i]; + tensor->data = (float*)malloc(sizeof(float)*mem_size); + tensor->tensor_type = TENSOR_TYPE_CONST; + + float* tmp = (float*)mem_ptr; + float* tr_tmp = (float*)tensor->data; + for(int i = 0; i < mem_size; i++) + { + tr_tmp[i] = tmp[i]; + } } set_ir_node_output_tensor(node, 0, tensor); tf_node->ir_node = node; @@ -249,6 +255,13 @@ int tensorflow_serializer::set_graph_input(ir_graph_t* graph) { dims[i] = shape.shape().dim(i).size(); } + if (dim_size == 4) + { + dims[0] = shape.shape().dim(0).size() == -1 ? 1 : shape.shape().dim(0).size(); + dims[1] = shape.shape().dim(3).size(); + dims[2] = shape.shape().dim(1).size(); + dims[3] = shape.shape().dim(2).size(); + } set_ir_tensor_shape(ir_tensor, dims, dim_size); } } @@ -263,10 +276,19 @@ int tensorflow_serializer::set_graph_input(ir_graph_t* graph) void* mem_ptr; std::vector tf_dims; std::string layout; - int dim_num = 0; - GetTensorContentAndDim(tf_tensor, dims, &mem_ptr, layout, dim_num); - dims = (int*)sys_malloc(tf_dims[0]); - memset(dims, 0, sizeof(int)*tf_dims[0]); + int dim_num = GetTensorContentAndDim(tf_tensor, &dims, &mem_ptr, layout); + + int mem_size = 1; + for(int i = 0; i < dim_num; i++) + mem_size *= dims[i]; + ir_tensor->data = (float*)malloc(sizeof(float)*mem_size); + ir_tensor->tensor_type = TENSOR_TYPE_CONST; + // tensor->data = mem_ptr; + float* tmp = (float*)mem_ptr; + float* tr_tmp = (float*)ir_tensor->data; + for(int i = 0; i < mem_size; i++) + tr_tmp[i] = tmp[i]; + int* reshape_dim = ( int* )mem_ptr; for(int i = 0; i < tf_dims[0]; i++) { @@ -304,7 +326,6 @@ int tensorflow_serializer::construct_graph() std::unordered_map node_map; /* first scan, setup all nodes */ - printf("tf node_number: %d \n", tf_net.node_size()); for(int i = 0; i < node_number; i++) { const tensorflow::NodeDef& node_param = tf_net.node(i); @@ -412,7 +433,7 @@ int DisconnectNode(TFNode* cur_node) cur_node->outputs.clear(); } -int MergeParentNode(TFNode* base_node, TFNode* parent_node) +int tensorflow_serializer::MergeParentNode(TFNode* base_node, TFNode* parent_node) { /* remove the input for parent node */ @@ -489,16 +510,16 @@ int MergeParentNode(TFNode* base_node, TFNode* parent_node) return 0; } -int CheckComposedBNAdd(TFNode* cur_node) +bool CheckComposedBNAdd(TFNode* cur_node) { if(cur_node->op != "Add") - return 0; + return false; TFNode* input0 = cur_node->inputs[0]; TFNode* input1 = cur_node->inputs[1]; if(input0->op != "Mul" || input1->op != "Sub") - return 0; + return false; /* further check: /add_1 int name */ if(cur_node->name.find("/add_1") != std::string::npos) @@ -508,13 +529,13 @@ int CheckComposedBNAdd(TFNode* cur_node) else cur_node->BNAddType = 0; - return 0; + return true; } - return -1; + return false; } -int BNRecursiveInputMerge(TFNode* node) +int tensorflow_serializer::BNRecursiveInputMerge(TFNode* node) { bool mul_1_node = false; bool mul_node = false; @@ -597,7 +618,7 @@ int BNRecursiveInputMerge(TFNode* node) MergeParentNode(node, input_node); } } -int FuseComposedBN(TFNode* cur_node) +int tensorflow_serializer::FuseComposedBN(TFNode* cur_node) { BNRecursiveInputMerge(cur_node); cur_node->op = "ComposedBN"; @@ -616,7 +637,7 @@ int FuseComposedBN(TFNode* cur_node) node->no_static_node = true; } } -int MergeChildNode(TFNode* base_node, TFNode* child_node) +int tensorflow_serializer::MergeChildNode(TFNode* base_node, TFNode* child_node) { auto output_ir = base_node->outputs.begin(); @@ -683,7 +704,7 @@ int MergeChildNode(TFNode* base_node, TFNode* child_node) } -void CleanupResizeNearestNeighbor(TFGraph& tf_graph) +void tensorflow_serializer::CleanupResizeNearestNeighbor() { auto ir = tf_graph.seq_nodes.begin(); @@ -745,7 +766,58 @@ int tensorflow_serializer::optimize_graph() { /* first clean up the predictions module of TF */ auto ir = tf_graph.seq_nodes.begin(); - + + while(ir != tf_graph.seq_nodes.end()) + { + TFNode* cur_node = *ir; + + if(cur_node->op == "Reshape") + { + /* Reshape should have two inputs */ + + TFNode* input_node0 = cur_node->inputs[0]; + TFNode* input_node1 = cur_node->inputs[1]; + + if(input_node0->op == "Softmax" || input_node1->op == "Softmax") + { + DisconnectNode(cur_node); + ir = tf_graph.seq_nodes.erase(ir); + delete cur_node; + continue; + } + + TFNode* output_node = cur_node->outputs[0]; + if(NULL == output_node) + continue; + + if(output_node->op == "Softmax" || output_node->op == "MatMul") + { + TFNode* input_node0 = cur_node->inputs[0]; + TFNode* input_node1 = cur_node->inputs[1]; + TFNode* input_node; + + if(input_node0->op == "Const") + { + DisconnectNode(input_node0); + input_node = input_node1; + } + else + { + DisconnectNode(input_node1); + input_node = input_node0; + } + + MergeChildNode(input_node, cur_node); + + ir = tf_graph.seq_nodes.erase(ir); + delete cur_node; + continue; + } + } + + ir++; + } + /* remove the squeeze node and identity */ ir = tf_graph.seq_nodes.begin(); @@ -927,7 +999,7 @@ int tensorflow_serializer::optimize_graph() } /* cleanup ResizeNearestNeighbor */ - CleanupResizeNearestNeighbor(tf_graph); + CleanupResizeNearestNeighbor(); /* merge Minimum and Relu */ @@ -1016,7 +1088,6 @@ int tensorflow_serializer::optimize_graph() DisconnectNode(padding_args); MergeParentNode(cur_node, input_node); - } } ir++; @@ -1749,7 +1820,6 @@ int tensorflow_serializer::generate_graph(ir_graph_t* graph) debug_graph = true; } - printf("node_number: %d \n", node_number); // first: create all tensor node for(i = 0; i < node_number; i++) { @@ -1763,120 +1833,155 @@ int tensorflow_serializer::generate_graph(ir_graph_t* graph) if(tf_node->no_static_node) continue; + if(tf_node->op == "Placeholder") + continue; + + if(tf_node->op == "Const") { load_const_tensor(tf_node, graph); continue; } + } - - // StaticNode* node = CreateStaticNode(graph, tf_node->name); - // std::string& op_name = tf_node->op; - ir_node_t* ir_node = create_ir_node(graph,tf_node->name.c_str(), op_load_map[tf_node->op].first, OP_VERSION); - /* create tensor */ - ir_tensor_t* ir_tensor = create_ir_tensor(graph, tf_node->name.c_str(), TENGINE_DT_FP32); - - set_ir_node_output_tensor(ir_node, 0, ir_tensor); - tf_node->ir_node = ir_node; - tf_node->ir_tensor = ir_tensor; - } - - std::vector no_supported_op; - for(i = 0; i < node_number; i++) - { - TFNode* tf_node = tf_graph.seq_nodes[i]; - - if(tf_node->op == "Placeholder" || tf_node->op == "Const") - continue; - - // if(!FindOpLoadMethod(tf_node->op)) - // { - // auto it = find(no_supported_op.begin(),no_supported_op.end(),tf_node->op); - // if(it != no_supported_op.end()) - // no_supported_op.push_back(tf_node->op); - // } - } - if(no_supported_op.size()) - { - TLOG_ERR("These ops are not supported \n", no_supported_op.size()); - TLOG_ERR("{"); - for(int j = 0; j < (int)no_supported_op.size(); j++) - { - TLOG_ERR("%d ", no_supported_op[j] ); - } - TLOG_ERR("}\n"); - return false; - } -// for(int i = 0; i < node_number; i++){ -// TFNode* tf_node = tf_graph.seq_nodes[i]; -// if(tf_node->op == "null" || tf_node->op == "Placeholder" || tf_node->op == "Const") -// continue; - -// std::vector::iterator iter=std::find(support_op.begin(), support_op.end(), tf_node->op); -// if(iter==support_op.end()){ -// std::vector::iterator uniter=std::find(unsupport_op.begin(), unsupport_op.end(), tf_node->op); -// if(uniter==unsupport_op.end()){ -// unsupport_op.push_back(tf_node->op); -// } else { -// continue; -// } -// } else { -// continue; -// } -// } -// if(unsupport_op.size() != 0){ -// printf("These ops are not in tensorflow serializer: \n"); -// for(int i = 0; i < (int)unsupport_op.size(); i++){ -// printf("[ %s ]\n", unsupport_op[i].c_str()); -// } -// printf("\n"); -// return false; -// } - for(i = 0; i < node_number; i++) + for(int i = 0; i < (int)tf_graph.seq_nodes.size(); i++) { TFNode* tf_node = tf_graph.seq_nodes[i]; if(tf_node->op == "Placeholder" || tf_node->op == "Const") continue; + ir_node_t* ir_node = nullptr; + int node_idx = get_ir_node_index_from_name(graph, tf_node->name.c_str()); + if(node_idx < 0) + { + ir_node = create_ir_node(graph, tf_node->name.c_str(), op_load_map[tf_node->op].first, OP_VERSION); + } + else + { + ir_node = get_ir_graph_node(graph, node_idx); + } + for(int in = 0; in < tf_node->inputs.size(); in++) + { + TFNode* node = tf_node->inputs[in]; + int tensor_idx = get_ir_tensor_index_from_name(graph, node->name.c_str()); + ir_tensor_t* tensor = nullptr; + if(node->name == "Placeholder") + { + continue; + } + if(tensor_idx < 0) + tensor = create_ir_tensor(graph, tf_node->name.c_str(),TENGINE_DT_FP32 ); + else + tensor = get_ir_graph_tensor(graph, tensor_idx); + set_ir_node_input_tensor(ir_node, in, tensor); + input_tensors.push_back(node->name.c_str()); + } + for(int out = 0; out < tf_node->outputs.size(); out++) + { + TFNode* node = tf_node->outputs[out]; + + int tensor_idx = get_ir_tensor_index_from_name(graph, node->name.c_str()); + ir_tensor_t* tensor = nullptr; + if(tensor_idx < 0) + tensor = create_ir_tensor(graph, tf_node->name.c_str(),TENGINE_DT_FP32 ); + else + tensor = get_ir_graph_tensor(graph, tensor_idx); + set_ir_node_output_tensor(ir_node, out, tensor); + output_tensors.push_back(node->name.c_str()); + } op_load_t loader = op_load_map[tf_node->op].second; - if (loader(graph, tf_node->ir_node, tf_node) < 0) + if (loader(tf_node, tf_graph, graph, ir_node) < 0) { fprintf(stderr, "load op %s func failed in node %s .\n", tf_node->op.c_str(), tf_node->name.c_str()); return -1; } + } + + // for(i = 0; i < (int)tf_graph.seq_nodes.size(); i++) + // { + // TFNode* tf_node = tf_graph.seq_nodes[i]; - // op_load_t loader = op_load_map[caffe_op_name].second; - // if (loader(graph, ir_node, layer_param) < 0) - // { - // TLOG_ERR("load op %s func failed in node %s .\n", caffe_op_name.c_str(), ir_node->name); - // return -1; - // } - } + // if(tf_node->op == "Placeholder" || tf_node->op == "Const") + // continue; + + + // op_load_t loader = op_load_map[tf_node->op].second; + // // printf("%s \n", tf_node->op.c_str()); + // if (loader(tf_node, tf_graph, graph) < 0) + // { + // fprintf(stderr, "load op %s func failed in node %s .\n", tf_node->op.c_str(), tf_node->name.c_str()); + // return -1; + // } + + // } if(i < node_number) - return false; + return -1; - return true; + return 0; } + +int tensorflow_serializer::set_graph_output(ir_graph_t* graph) +{ + int layer_number = tf_graph.seq_nodes.size(); + std::vector output_nodes; + + std::vector graph_outputs; + for (int i = 0; i < output_tensors.size(); i++) + { + int check_flag = true; + + auto it = find(input_tensors.begin(), input_tensors.end(), output_tensors[i]); + if (it == input_tensors.end()) + { + graph_outputs.push_back(output_tensors[i]); + } + } + + for (int i = 0; i < graph_outputs.size(); i++) + { + int tensor_id = get_ir_tensor_index_from_name(graph, graph_outputs[i].c_str()); + ir_tensor_t* tensor = nullptr; + if(tensor_id < 0) + tensor = create_ir_tensor(graph, graph_outputs[i].c_str(),TENGINE_DT_FP32 ); + else + tensor = get_ir_graph_tensor(graph, tensor_id); + int node_idx = get_ir_node_index_from_name(graph,graph_outputs[i].c_str() ); + ir_node_t* node = get_ir_graph_node(graph, node_idx); + set_ir_node_output_tensor(node, 0, tensor); + output_nodes.push_back(node->index); + } + + std::vector node_idx; + for (int i = 0; i < output_nodes.size(); i++) + { + node_idx.push_back(output_nodes[i]); + } + set_ir_graph_output_node(graph, node_idx.data(), output_nodes.size()); + return 0; + return 0; +} + int tensorflow_serializer::load_graph(ir_graph_t* graph) { - printf("tf_net node num : %d \n", tf_net.node_size()); if (construct_graph() < 0) return -1; - - if(optimize_rnn() < 0) + if (optimize_rnn() < 0) return false; - if (optimize_graph() < 0) return -1; - if (set_graph_input(graph) < 0) return -1; - - if(generate_graph(graph) < 0) + fprintf(stderr, "Process 2: Finish set graph input \n"); + if (generate_graph(graph) < 0) return -1; + fprintf(stderr, "Process 3: Finish load graph node \n"); + + if (set_graph_output(graph) < 0) + return -1; + fprintf(stderr, "Process 4: Finish set graph output \n"); return 0; } @@ -1888,18 +1993,8 @@ int tensorflow_serializer::load_model(ir_graph_t* graph, std::string model_file) if (load_binary_file(model_file) < 0) return -1; fprintf(stderr, "Process 1: Finish load protobuf file \n"); - // if (load_tensor_data(graph, test_net, train_net) < 0) - // return -1; - // fprintf(stderr, "Process 2: Finish load graph node \n"); - load_graph(graph); - // fprintf(stderr, "Process 3: Finish set graph input \n"); - // if (load_graph_node(graph, test_net, train_net) < 0) - // return -1; - // fprintf(stderr, "Process 4: Finish load graph node \n"); - // if (set_graph_output(graph, test_net, train_net) < 0) - // return -1; - // fprintf(stderr, "Process 5: Finish set graph output \n"); + return 0; } @@ -1928,7 +2023,265 @@ graph_t tensorflow_serializer::tensorflow2tengine(std::string model_file) return ir_graph; } -void tensorflow_serializer::register_op_load() +int load_pool(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* node) { + TFNode* input = tf_node->inputs[0]; + struct pool_param* param = (struct pool_param*)node->op.param_mem; + const tensorflow::NodeDef* node_def = tf_node->pb_defs[0]; + tensorflow::AttrValue value; + + if(GetAttrValue(node_def, "ksize", value)) + { + param->kernel_h = value.list().i(1); + param->kernel_w = value.list().i(2); + } + + if(GetAttrValue(node_def, "strides", value)) + { + param->stride_h = value.list().i(1); + param->stride_w = value.list().i(2); + } + if(GetAttrValue(node_def, "padding", value)) + { + if(value.s() == "VALID") + { + param->pad_h0 = 0; + param->pad_h1 = 0; + param->pad_w0 = 0; + param->pad_w1 = 0; + } + else if(value.s() == "SAME") + { + param->pad_h0 = -1; + param->pad_h1 = -1; + param->pad_w0 = -1; + param->pad_w1 = -1; + } + } + + if(tf_node->op == "AvgPool") + { + param->pool_method = 0; + } + else if(tf_node->op == "MaxPool") + { + param->pool_method = 1; + } + return 0; +} +int load_conv(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* node) +{ + TFNode* input0 = tf_node->inputs[0]; /* input */ + TFNode* input1 = tf_node->inputs[1]; /* weight */ + TFNode* input2 = nullptr; + if(tf_node->inputs.size() > 2) + { + input2 = tf_node->inputs[2]; + } + const tensorflow::NodeDef* node_def = tf_node->pb_defs[0]; + struct conv_param* param = (struct conv_param*)node->op.param_mem; + tensorflow::AttrValue value; + + if(GetAttrValue(node_def, "dilations", value)) + { + param->dilation_h = value.list().i(1); + param->dilation_w = value.list().i(2); + } + if(GetAttrValue(node_def, "padding", value)) + { + if(value.s() == "VALID") + { + param->pad_h0 = 0; + param->pad_h1 = 0; + param->pad_w0 = 0; + param->pad_w1 = 0; + } + else if(value.s() == "SAME") + { + param->pad_h0 = -1; + param->pad_h1 = -1; + param->pad_w0 = -1; + param->pad_w1 = -1; + } + } + + if(GetAttrValue(node_def, "strides", value)) + { + param->stride_h = value.list().i(1); + param->stride_w = value.list().i(2); + } + + int in_channel = 1, out_channel = 1, kernel_h = 0, kernel_w = 0; + int group = 1; + // Tensorflow has to get those information from weights + + const tensorflow::NodeDef* weight_def = input1->pb_defs[0]; + + if(GetAttrValue(weight_def, "value", value)) + { + const tensorflow::TensorShapeProto& shape = value.tensor().tensor_shape(); + + if(shape.dim_size() == 4) + { + kernel_h = shape.dim(0).size(); + kernel_w = shape.dim(1).size(); + in_channel = shape.dim(2).size(); + out_channel = shape.dim(3).size(); + } + else if(shape.dim_size() == 3) + { + kernel_h = 1; + kernel_w = shape.dim(0).size(); + in_channel = shape.dim(1).size(); + out_channel = shape.dim(2).size(); + } + } + ir_tensor_t* weight_tensor = input1->ir_tensor; + + int elem_size = out_channel * in_channel * kernel_h * kernel_w; + float* new_weight = ( float* )malloc(sizeof(float) * elem_size); + float* src = (float*)weight_tensor->data; + weight_tensor->data = sys_malloc(elem_size*sizeof(float)); + float* ptr = (float*)weight_tensor->data; + + for(int o = 0; o < out_channel; o++) + for(int h = 0; h < kernel_h; h++) + for(int w = 0; w < kernel_w; w++) + for(int i = 0; i < in_channel; i++) + { + ptr[o*in_channel*kernel_h*kernel_w + i*kernel_h*kernel_w + h*kernel_w + w] + = src[h * (kernel_w * in_channel * out_channel) + w * (in_channel * out_channel) + i * out_channel + o]; + } + + free(src); + + weight_tensor->tensor_type = TENSOR_TYPE_CONST; + if(tf_node->op == "DepthwiseConv2dNative") + { + group = in_channel; + out_channel = in_channel * out_channel; + in_channel = 1; + } + + int* dims = (int*)malloc(sizeof(int)*4); + dims[0] = out_channel; + dims[1] = in_channel; + dims[2] = kernel_h; + dims[3] = kernel_w; +#if 0 + dims.push_back(out_channel); + dims.push_back(kernel_h); + dims.push_back(kernel_w); + dims.push_back(in_channel); +// #else + dims.push_back(out_channel); + dims.push_back(in_channel); + dims.push_back(kernel_h); + dims.push_back(kernel_w); +#endif + // SetTensorDim(weight_tensor, dims); + set_ir_tensor_shape(weight_tensor, dims, 4); + param->kernel_h = kernel_h; + param->kernel_w = kernel_w; + param->output_channel = out_channel; + param->group = group; + + + if(tf_node->op == "DepthwiseConv2dNative") + { + in_channel = group; + out_channel = out_channel / in_channel; + } + + int pb_def_num = tf_node->pb_defs.size(); + + if(pb_def_num > 1) + { + // the last one, + const tensorflow::NodeDef* node_def = tf_node->pb_defs[pb_def_num - 1]; + + /* possible pad */ + if(node_def->op() == "Const") + { + tensorflow::AttrValue value; + + if(GetAttrValue(node_def, "value", value) && value.has_tensor()) + { + const tensorflow::TensorProto& tf_tensor = value.tensor(); + + int dim_size = tf_tensor.tensor_shape().dim_size(); + + if(dim_size == 2 && tf_tensor.tensor_shape().dim(0).size() == 4 && + tf_tensor.tensor_shape().dim(1).size() == 2) + { + std::vector shape_data(8); + + if(tf_tensor.tensor_content().size()) + { + // int* dst = shape_data.data(); + memcpy(ptr, tf_tensor.tensor_content().c_str(), tf_tensor.tensor_content().size()); + } + else + { + int data_num = tf_tensor.int_val_size(); + + for(int i = 0; i < data_num; i++) + { + shape_data[i] = tf_tensor.int_val(i); + } + } + + /* h pad */ + param->pad_h0 = shape_data[2]; + param->pad_h1 = shape_data[3]; + /* w pad */ + param->pad_w0 = shape_data[4]; + param->pad_w1 = shape_data[5]; + + } + } + } + } + return 0; +} +int load_batchnorm(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* node) +{ + struct batchnorm_param* param = (struct batchnorm_param*)node->op.param_mem; + const tensorflow::NodeDef* node_def = tf_node->pb_defs[0]; + tensorflow::AttrValue value; + + if(GetAttrValue(node_def, "epsilon", value)) + { + param->eps = value.f(); + } + + return 0; +} +int load_relu6(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* node) +{ + return 0; +} +int load_softmax(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* node) +{ + return 0; +} +int load_relu(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* node) +{ + TFNode* input = tf_node->inputs[0]; + struct relu_param* param = (struct relu_param*)node->op.param_mem; + param->negative_slope = 0.f; + return 0; +} + +void tensorflow_serializer::register_op_load() +{ + op_load_map["AvgPool"] = std::pair(OP_POOL, load_pool); + op_load_map["MaxPool"] = std::pair(OP_POOL, load_pool); + op_load_map["Conv2D"] = std::pair(OP_CONV, load_conv); + op_load_map["DepthwiseConv2dNative"] = std::pair(OP_CONV, load_conv); + op_load_map["FusedBatchNorm"] = std::pair(OP_BATCHNORM, load_batchnorm); + op_load_map["Relu6"] = std::pair(OP_RELU6, load_relu6); + op_load_map["Relu"] = std::pair(OP_RELU6, load_relu); + op_load_map["Softmax"] = std::pair(OP_SOFTMAX, load_softmax); } \ No newline at end of file diff --git a/tools/convert_tool/tensorflow/tf2tengine.hpp b/tools/convert_tool/tensorflow/tf2tengine.hpp index e23e9a80f..00505fb74 100644 --- a/tools/convert_tool/tensorflow/tf2tengine.hpp +++ b/tools/convert_tool/tensorflow/tf2tengine.hpp @@ -219,7 +219,7 @@ class tensorflow_serializer { public: graph_t tensorflow2tengine(std::string model_file); - typedef int (*op_load_t)(ir_graph_t* graph, ir_node_t* node,TFNode* tf_node); + typedef int (*op_load_t)(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* node); private: std::unordered_map > op_load_map; @@ -240,9 +240,16 @@ class tensorflow_serializer void ParseLSTMGraph(LSTMNode* lstm_node, std::set& rnn_graph); void StripRNNScope(std::string& rnn_scope, int rnn_type); void MergeReluMinimum(); + int MergeChildNode(TFNode* base_node, TFNode* child_node); + int MergeParentNode(TFNode* base_node, TFNode* child_node); + int BNRecursiveInputMerge(TFNode* node); + int FuseComposedBN(TFNode* cur_node); int optimize_rnn(); + void CleanupResizeNearestNeighbor(); tensorflow::GraphDef tf_net; TFGraph tf_graph; + std::vector input_tensors; + std::vector output_tensors; }; #endif \ No newline at end of file From c5e7cb7f0eb971fe8cd49737c85e6a7462c67b7a Mon Sep 17 00:00:00 2001 From: bzhang5 Date: Thu, 19 Aug 2021 08:14:58 +0000 Subject: [PATCH 3/8] apply code-format changes --- tools/convert_tool/tensorflow/tf2tengine.cpp | 643 +++++++++---------- tools/convert_tool/tensorflow/tf2tengine.hpp | 29 +- 2 files changed, 330 insertions(+), 342 deletions(-) diff --git a/tools/convert_tool/tensorflow/tf2tengine.cpp b/tools/convert_tool/tensorflow/tf2tengine.cpp index d925e731c..34cb2c000 100644 --- a/tools/convert_tool/tensorflow/tf2tengine.cpp +++ b/tools/convert_tool/tensorflow/tf2tengine.cpp @@ -53,7 +53,7 @@ static bool GetAttrValue(const tensorflow::NodeDef* node, const char* key, tenso const google::protobuf::Map& attr = node->attr(); const google::protobuf::Map::const_iterator it = attr.find(key); - if(it != attr.end()) + if (it != attr.end()) { value = it->second; return true; @@ -63,18 +63,18 @@ static bool GetAttrValue(const tensorflow::NodeDef* node, const char* key, tenso } int GetTensorContentAndDim(const tensorflow::TensorProto& tf_tensor, int** dims, void** mem_ptr, - std::string& layout) + std::string& layout) { const tensorflow::TensorShapeProto& shape = tf_tensor.tensor_shape(); int elem_num = 1; int dim_num = shape.dim_size(); - int* dim_tmp = (int*)malloc(sizeof(int)*dim_num); + int* dim_tmp = (int*)malloc(sizeof(int) * dim_num); // printf("dim num : %d \n", dim_num); // dims = (int*)malloc(sizeof(int)*dim_num); - for(int i = 0; i < dim_num; i++) + for (int i = 0; i < dim_num; i++) { elem_num *= shape.dim(i).size(); dim_tmp[i] = shape.dim(i).size(); @@ -82,22 +82,22 @@ int GetTensorContentAndDim(const tensorflow::TensorProto& tf_tensor, int** dims, void* mem_buf = nullptr; - if(tf_tensor.tensor_content().size()) + if (tf_tensor.tensor_content().size()) { int content_size = tf_tensor.tensor_content().size(); mem_buf = malloc(content_size + 128); - void* src = ( void* )tf_tensor.tensor_content().c_str(); + void* src = (void*)tf_tensor.tensor_content().c_str(); memcpy(mem_buf, src, content_size); } - else if(tf_tensor.dtype() == tensorflow::DataType::DT_FLOAT) + else if (tf_tensor.dtype() == tensorflow::DataType::DT_FLOAT) { // in packed format int data_num = tf_tensor.float_val_size(); mem_buf = malloc(elem_num * sizeof(float)); - float* mem = ( float* )mem_buf; - if(data_num >= elem_num) + float* mem = (float*)mem_buf; + if (data_num >= elem_num) { - for(int i = 0; i < elem_num; i++) + for (int i = 0; i < elem_num; i++) { mem[i] = tf_tensor.float_val(i); } @@ -105,28 +105,28 @@ int GetTensorContentAndDim(const tensorflow::TensorProto& tf_tensor, int** dims, else { // data_num < elem_num - for(int i = 0; i < data_num; i++) + for (int i = 0; i < data_num; i++) { mem[i] = tf_tensor.float_val(i); } - for(int i = data_num; i < elem_num; i++) + for (int i = data_num; i < elem_num; i++) { mem[i] = mem[data_num - 1]; } } } - else if(tf_tensor.dtype() == tensorflow::DataType::DT_INT32) + else if (tf_tensor.dtype() == tensorflow::DataType::DT_INT32) { int data_num = tf_tensor.int_val_size(); mem_buf = malloc(elem_num * sizeof(int)); - int* mem = ( int* )mem_buf; + int* mem = (int*)mem_buf; - if(data_num >= elem_num) + if (data_num >= elem_num) { - for(int i = 0; i < elem_num; i++) + for (int i = 0; i < elem_num; i++) { mem[i] = tf_tensor.int_val(i); } @@ -134,12 +134,12 @@ int GetTensorContentAndDim(const tensorflow::TensorProto& tf_tensor, int** dims, else { // data_num < elem_num - for(int i = 0; i < data_num; i++) + for (int i = 0; i < data_num; i++) { mem[i] = tf_tensor.int_val(i); } - for(int i = data_num; i < elem_num; i++) + for (int i = data_num; i < elem_num; i++) { mem[i] = mem[data_num - 1]; } @@ -148,22 +148,22 @@ int GetTensorContentAndDim(const tensorflow::TensorProto& tf_tensor, int** dims, *mem_ptr = mem_buf; *dims = dim_tmp; - switch(dim_num) - { - case 0: - layout = "W"; - break; - case 1: - layout = "W"; - break; - case 2: - layout = "HW"; - break; - case 4: - layout = "NCHW"; - break; - default: - break; + switch (dim_num) + { + case 0: + layout = "W"; + break; + case 1: + layout = "W"; + break; + case 2: + layout = "HW"; + break; + case 4: + layout = "NCHW"; + break; + default: + break; } return dim_num; } @@ -171,7 +171,7 @@ int tensorflow_serializer::load_binary_file(std::string model_file) { std::ifstream is(model_file.c_str(), std::ios::in | std::ios::binary); - if(!is.is_open()) + if (!is.is_open()) { TLOG_ERR("cannot open file: %s \n", model_file.c_str()); return false; @@ -189,9 +189,9 @@ int tensorflow_serializer::load_binary_file(std::string model_file) is.close(); - if(!ret) + if (!ret) { - TLOG_ERR( "parse file: %s failed\n",model_file.c_str()); + TLOG_ERR("parse file: %s failed\n", model_file.c_str()); return -1; } return ret; @@ -199,27 +199,27 @@ int tensorflow_serializer::load_binary_file(std::string model_file) int load_const_tensor(TFNode* tf_node, ir_graph_t* graph) { ir_node_t* node = create_ir_node(graph, tf_node->name.c_str(), OP_CONST, OP_VERSION); - ir_tensor_t* tensor = create_ir_tensor(graph, tf_node->name.c_str(),TENGINE_DT_FP32); + ir_tensor_t* tensor = create_ir_tensor(graph, tf_node->name.c_str(), TENGINE_DT_FP32); tensorflow::AttrValue value; const tensorflow::NodeDef* node_def = tf_node->pb_defs[0]; - if(GetAttrValue(node_def, "value", value)) + if (GetAttrValue(node_def, "value", value)) { const tensorflow::TensorProto& tf_tensor = value.tensor(); void* mem_ptr; - int* dims ; + int* dims; std::string layout; int dim_num = GetTensorContentAndDim(tf_tensor, &dims, &mem_ptr, layout); set_ir_tensor_shape(tensor, dims, dim_num); int mem_size = 1; - for(int i = 0; i < dim_num; i++) + for (int i = 0; i < dim_num; i++) mem_size *= dims[i]; - tensor->data = (float*)malloc(sizeof(float)*mem_size); + tensor->data = (float*)malloc(sizeof(float) * mem_size); tensor->tensor_type = TENSOR_TYPE_CONST; float* tmp = (float*)mem_ptr; float* tr_tmp = (float*)tensor->data; - for(int i = 0; i < mem_size; i++) + for (int i = 0; i < mem_size; i++) { tr_tmp[i] = tmp[i]; } @@ -233,25 +233,25 @@ int tensorflow_serializer::set_graph_input(ir_graph_t* graph) { int node_num = tf_graph.seq_nodes.size(); std::vector input_nodes; - for(int i = 0; i < node_num; i++) + for (int i = 0; i < node_num; i++) { - TFNode* tf_node =tf_graph.seq_nodes[i]; - if(tf_node->op == "Placeholder") + TFNode* tf_node = tf_graph.seq_nodes[i]; + if (tf_node->op == "Placeholder") { ir_tensor_t* ir_tensor = create_ir_tensor(graph, tf_node->name.c_str(), TENGINE_DT_FP32); tensorflow::AttrValue shape; int pb_defs_cnt = tf_node->pb_defs.size(); int* dims; - if(pb_defs_cnt == 1) + if (pb_defs_cnt == 1) { - if(GetAttrValue(tf_node->pb_defs[0], "shape", shape)) + if (GetAttrValue(tf_node->pb_defs[0], "shape", shape)) { int dim_size = shape.shape().dim_size(); - + dims = (int*)sys_malloc(dim_size); - memset(dims, 0, sizeof(int)*dim_size); - for(int i = 0; i < dim_size; ++i) + memset(dims, 0, sizeof(int) * dim_size); + for (int i = 0; i < dim_size; ++i) { dims[i] = shape.shape().dim(i).size(); } @@ -269,7 +269,7 @@ int tensorflow_serializer::set_graph_input(ir_graph_t* graph) { tensorflow::AttrValue value; const tensorflow::NodeDef* node_def = tf_node->pb_defs[pb_defs_cnt - 1]; - if(GetAttrValue(node_def, "value", value)) + if (GetAttrValue(node_def, "value", value)) { const tensorflow::TensorProto& tf_tensor = value.tensor(); @@ -279,32 +279,32 @@ int tensorflow_serializer::set_graph_input(ir_graph_t* graph) int dim_num = GetTensorContentAndDim(tf_tensor, &dims, &mem_ptr, layout); int mem_size = 1; - for(int i = 0; i < dim_num; i++) + for (int i = 0; i < dim_num; i++) mem_size *= dims[i]; - ir_tensor->data = (float*)malloc(sizeof(float)*mem_size); + ir_tensor->data = (float*)malloc(sizeof(float) * mem_size); ir_tensor->tensor_type = TENSOR_TYPE_CONST; // tensor->data = mem_ptr; float* tmp = (float*)mem_ptr; float* tr_tmp = (float*)ir_tensor->data; - for(int i = 0; i < mem_size; i++) + for (int i = 0; i < mem_size; i++) tr_tmp[i] = tmp[i]; - int* reshape_dim = ( int* )mem_ptr; - for(int i = 0; i < tf_dims[0]; i++) + int* reshape_dim = (int*)mem_ptr; + for (int i = 0; i < tf_dims[0]; i++) { dims[i] = reshape_dim[i]; } - for(unsigned int i = 0; i < tf_dims[0]; i++) + for (unsigned int i = 0; i < tf_dims[0]; i++) { - if(dims[i] == -1) + if (dims[i] == -1) dims[i] = 1; } free(mem_ptr); set_ir_tensor_shape(ir_tensor, dims, tf_dims[0]); } } - ir_node_t* node = create_ir_node(graph, tf_node->name.c_str(), OP_INPUT, OP_VERSION); + ir_node_t* node = create_ir_node(graph, tf_node->name.c_str(), OP_INPUT, OP_VERSION); int tensor_id = get_ir_tensor_index_from_name(graph, tf_node->name.c_str()); @@ -326,7 +326,7 @@ int tensorflow_serializer::construct_graph() std::unordered_map node_map; /* first scan, setup all nodes */ - for(int i = 0; i < node_number; i++) + for (int i = 0; i < node_number; i++) { const tensorflow::NodeDef& node_param = tf_net.node(i); @@ -343,30 +343,30 @@ int tensorflow_serializer::construct_graph() } /* the second scan, setup connections */ - for(int i = 0; i < node_number; i++) + for (int i = 0; i < node_number; i++) { const tensorflow::NodeDef& node_param = tf_net.node(i); const std::string& name = node_param.name(); TFNode* cur_node = node_map[name]; - for(int j = 0; j < node_param.input_size(); j++) + for (int j = 0; j < node_param.input_size(); j++) { const std::string& input_name = node_param.input(j); std::string::size_type pos = input_name.find(":"); std::string cleanup_name; - if(pos == std::string::npos) + if (pos == std::string::npos) pos = input_name.size(); - if(input_name[0] == '^') + if (input_name[0] == '^') cleanup_name = input_name.substr(1, pos); else cleanup_name = input_name.substr(0, pos); TFNode* input_node = node_map[cleanup_name]; - if(input_node == nullptr) + if (input_node == nullptr) { TLOG_ERR("cannot find input: %s for node: %s \n", input_name.c_str(), name.c_str()); return false; @@ -382,21 +382,21 @@ int DisconnectNode(TFNode* cur_node) { TFNode* input_node; - for(unsigned int i = 0; i < cur_node->inputs.size(); i++) + for (unsigned int i = 0; i < cur_node->inputs.size(); i++) { input_node = cur_node->inputs[i]; auto ir = input_node->outputs.begin(); - while(ir != input_node->outputs.end()) + while (ir != input_node->outputs.end()) { - if(*ir != cur_node) + if (*ir != cur_node) ir++; else break; } - if(ir == input_node->outputs.end()) + if (ir == input_node->outputs.end()) { TLOG_ERR("ERROR on node connection!!\n"); } @@ -408,21 +408,21 @@ int DisconnectNode(TFNode* cur_node) TFNode* output_node; - for(unsigned int i = 0; i < cur_node->outputs.size(); i++) + for (unsigned int i = 0; i < cur_node->outputs.size(); i++) { output_node = cur_node->outputs[i]; auto ir = output_node->inputs.begin(); - while(ir != output_node->inputs.end()) + while (ir != output_node->inputs.end()) { - if(*ir != cur_node) + if (*ir != cur_node) ir++; else break; } - if(ir == output_node->inputs.end()) + if (ir == output_node->inputs.end()) { TLOG_ERR("ERROR on node connection!!\n"); } @@ -439,15 +439,15 @@ int tensorflow_serializer::MergeParentNode(TFNode* base_node, TFNode* parent_nod auto input_ir = base_node->inputs.begin(); - while(input_ir != base_node->inputs.end()) + while (input_ir != base_node->inputs.end()) { - if(*input_ir == parent_node) + if (*input_ir == parent_node) break; input_ir++; } - if(parent_node->inputs.size() == 1) + if (parent_node->inputs.size() == 1) { *input_ir = parent_node->inputs[0]; } @@ -461,11 +461,11 @@ int tensorflow_serializer::MergeParentNode(TFNode* base_node, TFNode* parent_nod /* setup the outputs of parent node's parent */ - for(auto node : parent_node->inputs) + for (auto node : parent_node->inputs) { - for(unsigned int i = 0; i < node->outputs.size(); i++) + for (unsigned int i = 0; i < node->outputs.size(); i++) { - if(node->outputs[i] == parent_node) + if (node->outputs[i] == parent_node) { node->outputs[i] = base_node; break; @@ -477,17 +477,17 @@ int tensorflow_serializer::MergeParentNode(TFNode* base_node, TFNode* parent_nod auto output_ir = parent_node->outputs.begin(); - while(output_ir != parent_node->outputs.end()) + while (output_ir != parent_node->outputs.end()) { TFNode* node = *output_ir; - if(node != base_node) + if (node != base_node) { base_node->outputs.push_back(node); - for(unsigned int i = 0; i < node->inputs.size(); i++) + for (unsigned int i = 0; i < node->inputs.size(); i++) { - if(node->inputs[i] == parent_node) + if (node->inputs[i] == parent_node) { node->inputs[i] = base_node; break; @@ -512,19 +512,19 @@ int tensorflow_serializer::MergeParentNode(TFNode* base_node, TFNode* parent_nod bool CheckComposedBNAdd(TFNode* cur_node) { - if(cur_node->op != "Add") + if (cur_node->op != "Add") return false; TFNode* input0 = cur_node->inputs[0]; TFNode* input1 = cur_node->inputs[1]; - if(input0->op != "Mul" || input1->op != "Sub") + if (input0->op != "Mul" || input1->op != "Sub") return false; /* further check: /add_1 int name */ - if(cur_node->name.find("/add_1") != std::string::npos) + if (cur_node->name.find("/add_1") != std::string::npos) { - if(input0->name.find("/mul_1") != std::string::npos || input1->name.find("/mul_1") != std::string::npos) + if (input0->name.find("/mul_1") != std::string::npos || input1->name.find("/mul_1") != std::string::npos) cur_node->BNAddType = 1; else cur_node->BNAddType = 0; @@ -539,20 +539,20 @@ int tensorflow_serializer::BNRecursiveInputMerge(TFNode* node) { bool mul_1_node = false; bool mul_node = false; - if(node->name.find("/mul") != std::string::npos) + if (node->name.find("/mul") != std::string::npos) { - if(node->BNAddType == 1) + if (node->BNAddType == 1) { - if(node->name.find("/mul_1") != std::string::npos) + if (node->name.find("/mul_1") != std::string::npos) { mul_1_node = true; } - else if(node->name.find("/mul_2") == std::string::npos) + else if (node->name.find("/mul_2") == std::string::npos) { // disconnect the connection between mul and mul2 auto ir = node->outputs.begin(); - if((*ir)->name.find("/mul2") == std::string::npos) + if ((*ir)->name.find("/mul2") == std::string::npos) ir++; TFNode* mul2_node = *ir; @@ -561,7 +561,7 @@ int tensorflow_serializer::BNRecursiveInputMerge(TFNode* node) ir = mul2_node->inputs.begin(); - if((*ir)->name.find("/mul") == std::string::npos) + if ((*ir)->name.find("/mul") == std::string::npos) ir++; mul2_node->inputs.erase(ir); @@ -569,15 +569,15 @@ int tensorflow_serializer::BNRecursiveInputMerge(TFNode* node) } else { - if(node->name.find("/mul_1") != std::string::npos) + if (node->name.find("/mul_1") != std::string::npos) { // disconnect the connection between add_1 mul_1 auto ir = node->inputs.begin(); - if((*ir)->name.find("/add_1") == std::string::npos) + if ((*ir)->name.find("/add_1") == std::string::npos) ir++; - if((*ir)->name.find("/add_1") != std::string::npos) + if ((*ir)->name.find("/add_1") != std::string::npos) { TFNode* Rsqrt_node = *ir; @@ -585,7 +585,7 @@ int tensorflow_serializer::BNRecursiveInputMerge(TFNode* node) ir = Rsqrt_node->outputs.begin(); - if((*ir)->name.find("/mul_1") == std::string::npos) + if ((*ir)->name.find("/mul_1") == std::string::npos) ir++; Rsqrt_node->outputs.erase(ir); @@ -602,16 +602,16 @@ int tensorflow_serializer::BNRecursiveInputMerge(TFNode* node) int orig_input_size = node->inputs.size(); std::vector input_cpy = node->inputs; - for(int i = 0; i < orig_input_size; i++) + for (int i = 0; i < orig_input_size; i++) { - if(mul_node && i == 0) + if (mul_node && i == 0) continue; - if(mul_1_node && i == 0) + if (mul_1_node && i == 0) continue; TFNode* input_node = input_cpy[i]; input_node->BNAddType = node->BNAddType; - if(input_node->op == "Const") + if (input_node->op == "Const") continue; BNRecursiveInputMerge(input_node); @@ -629,11 +629,11 @@ int tensorflow_serializer::FuseComposedBN(TFNode* cur_node) /* skip to create static node for add/y */ - for(unsigned int i = 0; i < cur_node->inputs.size(); i++) + for (unsigned int i = 0; i < cur_node->inputs.size(); i++) { TFNode* node = cur_node->inputs[i]; - if(node->name.find("/add/y") != std::string::npos) + if (node->name.find("/add/y") != std::string::npos) node->no_static_node = true; } } @@ -641,14 +641,14 @@ int tensorflow_serializer::MergeChildNode(TFNode* base_node, TFNode* child_node) { auto output_ir = base_node->outputs.begin(); - while(output_ir != base_node->outputs.end()) + while (output_ir != base_node->outputs.end()) { - if(*output_ir == child_node) + if (*output_ir == child_node) break; output_ir++; } - if(child_node->outputs.size() == 1) + if (child_node->outputs.size() == 1) { *output_ir = child_node->outputs[0]; } @@ -658,11 +658,11 @@ int tensorflow_serializer::MergeChildNode(TFNode* base_node, TFNode* child_node) base_node->outputs.insert(base_node->outputs.end(), child_node->outputs.begin(), child_node->outputs.end()); } - for(auto node : child_node->outputs) + for (auto node : child_node->outputs) { - for(unsigned int i = 0; i < node->inputs.size(); i++) + for (unsigned int i = 0; i < node->inputs.size(); i++) { - if(node->inputs[i] == child_node) + if (node->inputs[i] == child_node) { node->inputs[i] = base_node; break; @@ -672,17 +672,17 @@ int tensorflow_serializer::MergeChildNode(TFNode* base_node, TFNode* child_node) auto ir = child_node->inputs.begin(); - while(ir != child_node->inputs.end()) + while (ir != child_node->inputs.end()) { TFNode* node = *ir; - if(node != base_node) + if (node != base_node) { base_node->inputs.push_back(node); - for(unsigned int i = 0; i < node->outputs.size(); i++) + for (unsigned int i = 0; i < node->outputs.size(); i++) { - if(node->outputs[i] == child_node) + if (node->outputs[i] == child_node) { node->outputs[i] = base_node; break; @@ -703,25 +703,24 @@ int tensorflow_serializer::MergeChildNode(TFNode* base_node, TFNode* child_node) return 0; } - void tensorflow_serializer::CleanupResizeNearestNeighbor() { auto ir = tf_graph.seq_nodes.begin(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if(cur_node->op == "ResizeNearestNeighbor") + if (cur_node->op == "ResizeNearestNeighbor") { TFNode* data_node = cur_node->inputs[0]; TFNode* data_shape_node = nullptr; - for(unsigned int i = 0; i < data_node->outputs.size(); i++) + for (unsigned int i = 0; i < data_node->outputs.size(); i++) { data_shape_node = data_node->outputs[i]; - if(data_shape_node->op == "Shape") + if (data_shape_node->op == "Shape") break; } @@ -737,19 +736,18 @@ void tensorflow_serializer::CleanupResizeNearestNeighbor() } } - void tensorflow_serializer::MergeReluMinimum() { - for(auto ir = tf_graph.seq_nodes.begin(); ir != tf_graph.seq_nodes.end(); ir++) + for (auto ir = tf_graph.seq_nodes.begin(); ir != tf_graph.seq_nodes.end(); ir++) { TFNode* cur_node = *ir; - if(cur_node->inputs.size() == 0) + if (cur_node->inputs.size() == 0) continue; TFNode* input0 = cur_node->inputs[0]; - if(cur_node->op == "Minimum" && input0->op == "Relu") + if (cur_node->op == "Minimum" && input0->op == "Relu") { TFNode* const_node = cur_node->inputs[1]; @@ -767,18 +765,18 @@ int tensorflow_serializer::optimize_graph() /* first clean up the predictions module of TF */ auto ir = tf_graph.seq_nodes.begin(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if(cur_node->op == "Reshape") + if (cur_node->op == "Reshape") { /* Reshape should have two inputs */ TFNode* input_node0 = cur_node->inputs[0]; TFNode* input_node1 = cur_node->inputs[1]; - if(input_node0->op == "Softmax" || input_node1->op == "Softmax") + if (input_node0->op == "Softmax" || input_node1->op == "Softmax") { DisconnectNode(cur_node); ir = tf_graph.seq_nodes.erase(ir); @@ -787,16 +785,16 @@ int tensorflow_serializer::optimize_graph() } TFNode* output_node = cur_node->outputs[0]; - if(NULL == output_node) + if (NULL == output_node) continue; - if(output_node->op == "Softmax" || output_node->op == "MatMul") + if (output_node->op == "Softmax" || output_node->op == "MatMul") { TFNode* input_node0 = cur_node->inputs[0]; TFNode* input_node1 = cur_node->inputs[1]; TFNode* input_node; - if(input_node0->op == "Const") + if (input_node0->op == "Const") { DisconnectNode(input_node0); input_node = input_node1; @@ -821,26 +819,26 @@ int tensorflow_serializer::optimize_graph() /* remove the squeeze node and identity */ ir = tf_graph.seq_nodes.begin(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if(cur_node->op == "Squeeze") + if (cur_node->op == "Squeeze") { TFNode* softmax_node = nullptr; TFNode* shape_node = nullptr; - for(unsigned int j = 0; j < cur_node->outputs.size(); j++) + for (unsigned int j = 0; j < cur_node->outputs.size(); j++) { - if(cur_node->outputs[j]->op == "Softmax") + if (cur_node->outputs[j]->op == "Softmax") softmax_node = cur_node->outputs[j]; - else if(cur_node->outputs[j]->op == "Shape") + else if (cur_node->outputs[j]->op == "Shape") shape_node = cur_node->outputs[j]; } - if(softmax_node) + if (softmax_node) { - if(shape_node) + if (shape_node) DisconnectNode(shape_node); TFNode* input_node = cur_node->inputs[0]; @@ -850,7 +848,7 @@ int tensorflow_serializer::optimize_graph() continue; } - if(cur_node->outputs.size() == 1 && softmax_node == nullptr) + if (cur_node->outputs.size() == 1 && softmax_node == nullptr) { TFNode* child_node = cur_node->outputs[0]; @@ -861,7 +859,7 @@ int tensorflow_serializer::optimize_graph() } } - if(cur_node->op == "Identity") + if (cur_node->op == "Identity") { TFNode* input_node = cur_node->inputs[0]; MergeChildNode(input_node, cur_node); @@ -871,22 +869,22 @@ int tensorflow_serializer::optimize_graph() continue; } - if(cur_node->op == "ConcatV2") + if (cur_node->op == "ConcatV2") { TFNode* axis_node = nullptr; - for(unsigned int i = 0; i < cur_node->inputs.size(); i++) + for (unsigned int i = 0; i < cur_node->inputs.size(); i++) { TFNode* check_node = cur_node->inputs[i]; - if(check_node->op == "Const") + if (check_node->op == "Const") { axis_node = check_node; break; } } - if(axis_node) + if (axis_node) { cur_node->pb_defs.push_back(axis_node->pb_defs[0]); DisconnectNode(axis_node); @@ -900,15 +898,15 @@ int tensorflow_serializer::optimize_graph() ir = tf_graph.seq_nodes.begin(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if(cur_node->op == "FIFOQueueV2") + if (cur_node->op == "FIFOQueueV2") { TFNode* queue_node = cur_node->outputs[0]; - if(queue_node->op == "QueueDequeueManyV2") + if (queue_node->op == "QueueDequeueManyV2") { MergeParentNode(queue_node, queue_node->inputs[1]); } @@ -924,16 +922,16 @@ int tensorflow_serializer::optimize_graph() /* remove ExpandDims */ ir = tf_graph.seq_nodes.begin(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if(cur_node->op == "ExpandDims") + if (cur_node->op == "ExpandDims") { TFNode* input0 = cur_node->inputs[0]; TFNode* input1 = cur_node->inputs[1]; - if(input0->op == "Constant" && input1->op == "Const") + if (input0->op == "Constant" && input1->op == "Const") { TFNode* input1 = cur_node->inputs[1]; TFNode* child_node = cur_node->outputs[0]; @@ -946,7 +944,7 @@ int tensorflow_serializer::optimize_graph() } else { - if(input1->op == "Const") + if (input1->op == "Const") DisconnectNode(input1); else DisconnectNode(input0); @@ -968,15 +966,15 @@ int tensorflow_serializer::optimize_graph() /* merge biasadd and conv */ ir = tf_graph.seq_nodes.begin(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if(cur_node->op == "Conv2D" || cur_node->op == "DepthwiseConv2dNative" || cur_node->op == "MatMul") + if (cur_node->op == "Conv2D" || cur_node->op == "DepthwiseConv2dNative" || cur_node->op == "MatMul") { TFNode* output_node = cur_node->outputs[0]; - if(output_node->op == "BiasAdd" || output_node->op == "Add") + if (output_node->op == "BiasAdd" || output_node->op == "Add") { MergeChildNode(cur_node, output_node); } @@ -989,11 +987,11 @@ int tensorflow_serializer::optimize_graph() ir = tf_graph.seq_nodes.begin(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if(CheckComposedBNAdd(cur_node)) + if (CheckComposedBNAdd(cur_node)) FuseComposedBN(cur_node); ir++; } @@ -1006,21 +1004,21 @@ int tensorflow_serializer::optimize_graph() MergeReluMinimum(); /* merge input node and reshape */ ir = tf_graph.seq_nodes.begin(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if(cur_node->op == "Reshape") + if (cur_node->op == "Reshape") { /* Reshape should have two inputs */ TFNode* input_node0 = cur_node->inputs[0]; TFNode* input_node1 = cur_node->inputs[1]; - if(input_node0->op == "Placeholder" || input_node1->op == "Placeholder") + if (input_node0->op == "Placeholder" || input_node1->op == "Placeholder") { TFNode* input_node; TFNode* const_node; - if(input_node0->op == "Const") + if (input_node0->op == "Const") { const_node = input_node0; input_node = input_node1; @@ -1047,15 +1045,15 @@ int tensorflow_serializer::optimize_graph() ir = tf_graph.seq_nodes.begin(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if(cur_node->op == "StridedSlice") + if (cur_node->op == "StridedSlice") { /* check if input0 is "shape" */ TFNode* input_node = cur_node->inputs[0]; - if(input_node->op == "Shape") + if (input_node->op == "Shape") { /* here we go */ DisconnectNode(cur_node); @@ -1071,16 +1069,16 @@ int tensorflow_serializer::optimize_graph() ir = tf_graph.seq_nodes.begin(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if(cur_node->op == "Conv2D" || cur_node->op == "DepthwiseConv2dNative") + if (cur_node->op == "Conv2D" || cur_node->op == "DepthwiseConv2dNative") { /* check if input is pad or not */ TFNode* input_node = cur_node->inputs[0]; - if(input_node->op == "Pad") + if (input_node->op == "Pad") { TFNode* padding_args = input_node->inputs[1]; @@ -1096,10 +1094,10 @@ int tensorflow_serializer::optimize_graph() /*remove ArgMax node */ ir = tf_graph.seq_nodes.begin(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if(cur_node->op == "ArgMax") + if (cur_node->op == "ArgMax") { DisconnectNode(cur_node); tf_graph.seq_nodes.erase(ir); @@ -1114,11 +1112,11 @@ int tensorflow_serializer::optimize_graph() ir = tf_graph.seq_nodes.begin(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if(cur_node->op == "Squeeze" && cur_node->outputs.empty()) + if (cur_node->op == "Squeeze" && cur_node->outputs.empty()) { DisconnectNode(cur_node); break; @@ -1130,11 +1128,11 @@ int tensorflow_serializer::optimize_graph() ir = tf_graph.seq_nodes.begin(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if(cur_node->inputs.size() == 0 && cur_node->outputs.size() == 0) + if (cur_node->inputs.size() == 0 && cur_node->outputs.size() == 0) { ir = tf_graph.seq_nodes.erase(ir); delete cur_node; @@ -1146,18 +1144,17 @@ int tensorflow_serializer::optimize_graph() /* remove no input but not placeholder/const nodes */ ir = tf_graph.seq_nodes.begin(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if(cur_node->inputs.size() == 0 && cur_node->op != "Const" && cur_node->op != "Placeholder" && - cur_node->op != "FIFOQueueV2") + if (cur_node->inputs.size() == 0 && cur_node->op != "Const" && cur_node->op != "Placeholder" && cur_node->op != "FIFOQueueV2") { DisconnectNode(cur_node); tf_graph.seq_nodes.erase(ir); delete cur_node; - ir = tf_graph.seq_nodes.begin(); // restart + ir = tf_graph.seq_nodes.begin(); // restart } else ir++; @@ -1166,7 +1163,6 @@ int tensorflow_serializer::optimize_graph() return 0; } - int tensorflow_serializer::FindRNNScope(std::string& rnn_scope) { std::string rnn_node; @@ -1175,19 +1171,19 @@ int tensorflow_serializer::FindRNNScope(std::string& rnn_scope) int rnn_type = -1; - for(unsigned int i = 0; i < tf_graph.seq_nodes.size(); i++) + for (unsigned int i = 0; i < tf_graph.seq_nodes.size(); i++) { TFNode* node = tf_graph.seq_nodes.at(i); std::string& name = node->name; while_pos = name.find("while"); - if(while_pos == std::string::npos) + if (while_pos == std::string::npos) continue; std::string::size_type cell_pos = name.find("lstm_cell", while_pos); - if(cell_pos != std::string::npos) + if (cell_pos != std::string::npos) { rnn_node = node->name; rnn_type = TF_RNN_LSTM; @@ -1196,7 +1192,7 @@ int tensorflow_serializer::FindRNNScope(std::string& rnn_scope) cell_pos = name.find("gru_cell", while_pos); - if(cell_pos != std::string::npos) + if (cell_pos != std::string::npos) { rnn_node = node->name; rnn_type = TF_RNN_GRU; @@ -1205,7 +1201,7 @@ int tensorflow_serializer::FindRNNScope(std::string& rnn_scope) cell_pos = name.find("basic_lstm_cell", while_pos); - if(cell_pos != std::string::npos) + if (cell_pos != std::string::npos) { rnn_node = node->name; rnn_type = TF_RNN_BASIC_LSTM; @@ -1214,7 +1210,7 @@ int tensorflow_serializer::FindRNNScope(std::string& rnn_scope) cell_pos = name.find("basic_rnn_cell", while_pos); - if(cell_pos != std::string::npos) + if (cell_pos != std::string::npos) { rnn_node = node->name; rnn_type = TF_RNN_BASIC_RNN; @@ -1222,7 +1218,7 @@ int tensorflow_serializer::FindRNNScope(std::string& rnn_scope) } } - if(rnn_node.empty()) + if (rnn_node.empty()) return -1; std::string rnn_layer = rnn_node.substr(0, while_pos - 1); @@ -1237,36 +1233,36 @@ void tensorflow_serializer::ParseLSTMGraph(LSTMNode* lstm_node, std::setinputs.size(); i++) + for (unsigned int i = 0; i < lstm_node->inputs.size(); i++) { TFNode* node = lstm_node->inputs[i]; - if(node->op != "Const") + if (node->op != "Const") continue; // node->no_static_node=true; //do not automatically create Static Node - if(node->name.find("lstm_cell/kernel") != std::string::npos) + if (node->name.find("lstm_cell/kernel") != std::string::npos) { lstm_node->kernel = node; } - else if(node->name.find("lstm_cell/bias") != std::string::npos) + else if (node->name.find("lstm_cell/bias") != std::string::npos) { lstm_node->bias = node; } - else if(node->name.find("lstm_cell/w_f_diag") != std::string::npos) + else if (node->name.find("lstm_cell/w_f_diag") != std::string::npos) { lstm_node->w_f_diag = node; } - else if(node->name.find("lstm_cell/w_o_diag") != std::string::npos) + else if (node->name.find("lstm_cell/w_o_diag") != std::string::npos) { lstm_node->w_o_diag = node; } - else if(node->name.find("lstm_cell/w_i_diag") != std::string::npos) + else if (node->name.find("lstm_cell/w_i_diag") != std::string::npos) { lstm_node->w_i_diag = node; } - else if(node->name.find("lstm_cell/projection/kernel") != std::string::npos) + else if (node->name.find("lstm_cell/projection/kernel") != std::string::npos) { lstm_node->projection = node; } @@ -1275,7 +1271,7 @@ void tensorflow_serializer::ParseLSTMGraph(LSTMNode* lstm_node, std::setname.size(); @@ -1283,11 +1279,11 @@ void tensorflow_serializer::ParseLSTMGraph(LSTMNode* lstm_node, std::setname.find(zero_name, name_len - zero_name.size()) != std::string::npos) + if (node->name.find(zero_name, name_len - zero_name.size()) != std::string::npos) lstm_node->init_c = node; - else if(node->name.find(zero1_name, name_len - zero1_name.size()) != std::string::npos) + else if (node->name.find(zero1_name, name_len - zero1_name.size()) != std::string::npos) lstm_node->init_h = node; - else if(node->name.find(forget_name, name_len - forget_name.size()) != std::string::npos) + else if (node->name.find(forget_name, name_len - forget_name.size()) != std::string::npos) lstm_node->forget_bias = node; rnn_ir++; @@ -1297,28 +1293,28 @@ void ParseGRUGraph(TFGraph& tf_graph, GRUNode* gru_node, std::set& rnn_ { /* parse input node */ - for(unsigned int i = 0; i < gru_node->inputs.size(); i++) + for (unsigned int i = 0; i < gru_node->inputs.size(); i++) { TFNode* node = gru_node->inputs[i]; - if(node->op != "Const") + if (node->op != "Const") continue; // node->no_static_node=true; //do not automatically create Static Node - if(node->name.find("gru_cell/gates/kernel") != std::string::npos) + if (node->name.find("gru_cell/gates/kernel") != std::string::npos) { gru_node->gate_kernel = node; } - else if(node->name.find("gru_cell/gates/bias") != std::string::npos) + else if (node->name.find("gru_cell/gates/bias") != std::string::npos) { gru_node->gate_bias = node; } - else if(node->name.find("gru_cell/candidate/kernel") != std::string::npos) + else if (node->name.find("gru_cell/candidate/kernel") != std::string::npos) { gru_node->candidate_kernel = node; } - else if(node->name.find("gru_cell/candidate/bias") != std::string::npos) + else if (node->name.find("gru_cell/candidate/bias") != std::string::npos) { gru_node->candidate_bias = node; } @@ -1327,13 +1323,13 @@ void ParseGRUGraph(TFGraph& tf_graph, GRUNode* gru_node, std::set& rnn_ auto rnn_ir = rnn_graph.begin(); auto rnn_ir_end = rnn_graph.end(); - while(rnn_ir != rnn_ir_end) + while (rnn_ir != rnn_ir_end) { TFNode* node = *rnn_ir; int name_len = node->name.size(); std::string zero_name = "GRUCellZeroState/zeros"; - if(node->name.find(zero_name, name_len - zero_name.size()) != std::string::npos) + if (node->name.find(zero_name, name_len - zero_name.size()) != std::string::npos) gru_node->init_h = node; rnn_ir++; @@ -1343,20 +1339,20 @@ void ParseRNNGraph(TFGraph& tf_graph, RNNNode* rnn_node, std::set& rnn_ { /* parse input node */ - for(unsigned int i = 0; i < rnn_node->inputs.size(); i++) + for (unsigned int i = 0; i < rnn_node->inputs.size(); i++) { TFNode* node = rnn_node->inputs[i]; - if(node->op != "Const") + if (node->op != "Const") continue; // node->no_static_node=true; //do not automatically create Static Node - if(node->name.find("basic_rnn_cell/kernel") != std::string::npos) + if (node->name.find("basic_rnn_cell/kernel") != std::string::npos) { rnn_node->kernel = node; } - else if(node->name.find("basic_rnn_cell/bias") != std::string::npos) + else if (node->name.find("basic_rnn_cell/bias") != std::string::npos) { rnn_node->bias = node; } @@ -1365,13 +1361,13 @@ void ParseRNNGraph(TFGraph& tf_graph, RNNNode* rnn_node, std::set& rnn_ auto rnn_ir = rnn_graph.begin(); auto rnn_ir_end = rnn_graph.end(); - while(rnn_ir != rnn_ir_end) + while (rnn_ir != rnn_ir_end) { TFNode* node = *rnn_ir; int name_len = node->name.size(); std::string zero_name = "BasicRNNCellZeroState/zeros"; - if(node->name.find(zero_name, name_len - zero_name.size()) != std::string::npos) + if (node->name.find(zero_name, name_len - zero_name.size()) != std::string::npos) rnn_node->init_h = node; rnn_ir++; @@ -1381,7 +1377,7 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) { // collect attributes according to rnn_type - if(rnn_type == TF_RNN_LSTM) + if (rnn_type == TF_RNN_LSTM) { LSTMNode* lstm_node = new LSTMNode(); @@ -1396,11 +1392,11 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) auto ir = tf_graph.seq_nodes.begin(); std::string::size_type prefix_len = rnn_scope.size(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* node = *ir; - if(node->name.find(rnn_scope.c_str(), 0, prefix_len) == std::string::npos) + if (node->name.find(rnn_scope.c_str(), 0, prefix_len) == std::string::npos) { ir++; continue; @@ -1415,23 +1411,23 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) auto rnn_ir = rnn_graph.begin(); auto rnn_end = rnn_graph.end(); - while(rnn_ir != rnn_end) + while (rnn_ir != rnn_end) { TFNode* node = *rnn_ir; - for(unsigned int i = 0; i < node->inputs.size(); i++) + for (unsigned int i = 0; i < node->inputs.size(); i++) { TFNode* input = node->inputs[i]; - if(!rnn_graph.count(input)) + if (!rnn_graph.count(input)) rnn_inputs.insert(input); } - for(unsigned int i = 0; i < node->outputs.size(); i++) + for (unsigned int i = 0; i < node->outputs.size(); i++) { TFNode* output = node->outputs[i]; - if(!rnn_graph.count(output)) + if (!rnn_graph.count(output)) rnn_outputs.insert(output); } @@ -1441,11 +1437,11 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) // insert lstm node auto seq_ir = tf_graph.seq_nodes.begin(); - while(seq_ir != tf_graph.seq_nodes.end()) + while (seq_ir != tf_graph.seq_nodes.end()) { TFNode* node = *seq_ir; - if(rnn_inputs.count(node)) + if (rnn_inputs.count(node)) { tf_graph.seq_nodes.insert(seq_ir, lstm_node); break; @@ -1458,21 +1454,21 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) auto set_ir = rnn_inputs.begin(); auto set_ir_end = rnn_inputs.end(); - while(set_ir != set_ir_end) + while (set_ir != set_ir_end) { TFNode* input_node = *set_ir; - for(unsigned int j = 0; j < input_node->outputs.size(); j++) + for (unsigned int j = 0; j < input_node->outputs.size(); j++) { TFNode* child_node = input_node->outputs[j]; - if(rnn_graph.count(child_node)) + if (rnn_graph.count(child_node)) input_node->outputs[j] = lstm_node; } lstm_node->inputs.push_back(input_node); - if(input_node->op == "Identity") + if (input_node->op == "Identity") { TFNode* parent_node = input_node->inputs[0]; @@ -1485,15 +1481,15 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) set_ir = rnn_outputs.begin(); set_ir_end = rnn_outputs.end(); - while(set_ir != set_ir_end) + while (set_ir != set_ir_end) { TFNode* output_node = *set_ir; - for(unsigned int j = 0; j < output_node->inputs.size(); j++) + for (unsigned int j = 0; j < output_node->inputs.size(); j++) { TFNode* parent_node = output_node->inputs[j]; - if(rnn_graph.count(parent_node)) + if (rnn_graph.count(parent_node)) output_node->inputs[j] = lstm_node; } @@ -1511,7 +1507,7 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) ParseLSTMGraph(lstm_node, rnn_graph); } - if(rnn_type == TF_RNN_BASIC_RNN) + if (rnn_type == TF_RNN_BASIC_RNN) { RNNNode* rnn_node = new RNNNode(); @@ -1527,11 +1523,11 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) auto ir = tf_graph.seq_nodes.begin(); std::string::size_type prefix_len = rnn_scope.size(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* node = *ir; - if(node->name.find(rnn_scope.c_str(), 0, prefix_len) == std::string::npos) + if (node->name.find(rnn_scope.c_str(), 0, prefix_len) == std::string::npos) { ir++; continue; @@ -1546,23 +1542,23 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) auto rnn_ir = rnn_graph.begin(); auto rnn_end = rnn_graph.end(); - while(rnn_ir != rnn_end) + while (rnn_ir != rnn_end) { TFNode* node = *rnn_ir; - for(unsigned int i = 0; i < node->inputs.size(); i++) + for (unsigned int i = 0; i < node->inputs.size(); i++) { TFNode* input = node->inputs[i]; - if(!rnn_graph.count(input)) + if (!rnn_graph.count(input)) rnn_inputs.insert(input); } - for(unsigned int i = 0; i < node->outputs.size(); i++) + for (unsigned int i = 0; i < node->outputs.size(); i++) { TFNode* output = node->outputs[i]; - if(!rnn_graph.count(output)) + if (!rnn_graph.count(output)) rnn_outputs.insert(output); } @@ -1572,11 +1568,11 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) // insert rnn node auto seq_ir = tf_graph.seq_nodes.begin(); - while(seq_ir != tf_graph.seq_nodes.end()) + while (seq_ir != tf_graph.seq_nodes.end()) { TFNode* node = *seq_ir; - if(rnn_inputs.count(node)) + if (rnn_inputs.count(node)) { tf_graph.seq_nodes.insert(seq_ir, rnn_node); break; @@ -1589,21 +1585,21 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) auto set_ir = rnn_inputs.begin(); auto set_ir_end = rnn_inputs.end(); - while(set_ir != set_ir_end) + while (set_ir != set_ir_end) { TFNode* input_node = *set_ir; - for(unsigned int j = 0; j < input_node->outputs.size(); j++) + for (unsigned int j = 0; j < input_node->outputs.size(); j++) { TFNode* child_node = input_node->outputs[j]; - if(rnn_graph.count(child_node)) + if (rnn_graph.count(child_node)) input_node->outputs[j] = rnn_node; } rnn_node->inputs.push_back(input_node); - if(input_node->op == "Identity") + if (input_node->op == "Identity") { TFNode* parent_node = input_node->inputs[0]; @@ -1616,15 +1612,15 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) set_ir = rnn_outputs.begin(); set_ir_end = rnn_outputs.end(); - while(set_ir != set_ir_end) + while (set_ir != set_ir_end) { TFNode* output_node = *set_ir; - for(unsigned int j = 0; j < output_node->inputs.size(); j++) + for (unsigned int j = 0; j < output_node->inputs.size(); j++) { TFNode* parent_node = output_node->inputs[j]; - if(rnn_graph.count(parent_node)) + if (rnn_graph.count(parent_node)) output_node->inputs[j] = rnn_node; } @@ -1641,7 +1637,7 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) ParseRNNGraph(tf_graph, rnn_node, rnn_graph); } - if(rnn_type == TF_RNN_GRU) + if (rnn_type == TF_RNN_GRU) { GRUNode* gru_node = new GRUNode(); @@ -1657,11 +1653,11 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) auto ir = tf_graph.seq_nodes.begin(); std::string::size_type prefix_len = rnn_scope.size(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* node = *ir; - if(node->name.find(rnn_scope.c_str(), 0, prefix_len) == std::string::npos) + if (node->name.find(rnn_scope.c_str(), 0, prefix_len) == std::string::npos) { ir++; continue; @@ -1676,23 +1672,23 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) auto rnn_ir = rnn_graph.begin(); auto rnn_end = rnn_graph.end(); - while(rnn_ir != rnn_end) + while (rnn_ir != rnn_end) { TFNode* node = *rnn_ir; - for(unsigned int i = 0; i < node->inputs.size(); i++) + for (unsigned int i = 0; i < node->inputs.size(); i++) { TFNode* input = node->inputs[i]; - if(!rnn_graph.count(input)) + if (!rnn_graph.count(input)) rnn_inputs.insert(input); } - for(unsigned int i = 0; i < node->outputs.size(); i++) + for (unsigned int i = 0; i < node->outputs.size(); i++) { TFNode* output = node->outputs[i]; - if(!rnn_graph.count(output)) + if (!rnn_graph.count(output)) rnn_outputs.insert(output); } @@ -1702,11 +1698,11 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) // insert rnn node auto seq_ir = tf_graph.seq_nodes.begin(); - while(seq_ir != tf_graph.seq_nodes.end()) + while (seq_ir != tf_graph.seq_nodes.end()) { TFNode* node = *seq_ir; - if(rnn_inputs.count(node)) + if (rnn_inputs.count(node)) { tf_graph.seq_nodes.insert(seq_ir, gru_node); break; @@ -1719,21 +1715,21 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) auto set_ir = rnn_inputs.begin(); auto set_ir_end = rnn_inputs.end(); - while(set_ir != set_ir_end) + while (set_ir != set_ir_end) { TFNode* input_node = *set_ir; - for(unsigned int j = 0; j < input_node->outputs.size(); j++) + for (unsigned int j = 0; j < input_node->outputs.size(); j++) { TFNode* child_node = input_node->outputs[j]; - if(rnn_graph.count(child_node)) + if (rnn_graph.count(child_node)) input_node->outputs[j] = gru_node; } gru_node->inputs.push_back(input_node); - if(input_node->op == "Identity") + if (input_node->op == "Identity") { TFNode* parent_node = input_node->inputs[0]; @@ -1746,15 +1742,15 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) set_ir = rnn_outputs.begin(); set_ir_end = rnn_outputs.end(); - while(set_ir != set_ir_end) + while (set_ir != set_ir_end) { TFNode* output_node = *set_ir; - for(unsigned int j = 0; j < output_node->inputs.size(); j++) + for (unsigned int j = 0; j < output_node->inputs.size(); j++) { TFNode* parent_node = output_node->inputs[j]; - if(rnn_graph.count(parent_node)) + if (rnn_graph.count(parent_node)) output_node->inputs[j] = gru_node; } @@ -1775,11 +1771,11 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) // cleanup zero in/zero out node auto seq_ir = tf_graph.seq_nodes.begin(); - while(seq_ir != tf_graph.seq_nodes.end()) + while (seq_ir != tf_graph.seq_nodes.end()) { TFNode* node = *seq_ir; - if(node->inputs.size() == 0 && node->outputs.size() == 0) + if (node->inputs.size() == 0 && node->outputs.size() == 0) { delete node; seq_ir = tf_graph.seq_nodes.erase(seq_ir); @@ -1792,13 +1788,13 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) } int tensorflow_serializer::optimize_rnn() { - while(1) + while (1) { std::string rnn_scope; int rnn_type = FindRNNScope(rnn_scope); - if(rnn_scope.empty()) + if (rnn_scope.empty()) break; StripRNNScope(rnn_scope, rnn_type); @@ -1807,7 +1803,6 @@ int tensorflow_serializer::optimize_rnn() return true; } - int tensorflow_serializer::generate_graph(ir_graph_t* graph) { int node_number = tf_graph.seq_nodes.size(); @@ -1815,45 +1810,44 @@ int tensorflow_serializer::generate_graph(ir_graph_t* graph) bool debug_graph = false; const char* debug_env = std::getenv("DEBUG_TF"); - if((debug_env) && (debug_env[0] == '1')) + if ((debug_env) && (debug_env[0] == '1')) { debug_graph = true; } // first: create all tensor node - for(i = 0; i < node_number; i++) + for (i = 0; i < node_number; i++) { TFNode* tf_node = tf_graph.seq_nodes[i]; - if(debug_graph) + if (debug_graph) { std::cout << i << "\t" << tf_node->op << "\t" << tf_node->name << "\n"; } - if(tf_node->no_static_node) + if (tf_node->no_static_node) continue; - if(tf_node->op == "Placeholder") + if (tf_node->op == "Placeholder") continue; - - if(tf_node->op == "Const") + if (tf_node->op == "Const") { load_const_tensor(tf_node, graph); continue; } - } + } - for(int i = 0; i < (int)tf_graph.seq_nodes.size(); i++) + for (int i = 0; i < (int)tf_graph.seq_nodes.size(); i++) { TFNode* tf_node = tf_graph.seq_nodes[i]; - if(tf_node->op == "Placeholder" || tf_node->op == "Const") + if (tf_node->op == "Placeholder" || tf_node->op == "Const") continue; ir_node_t* ir_node = nullptr; int node_idx = get_ir_node_index_from_name(graph, tf_node->name.c_str()); - if(node_idx < 0) + if (node_idx < 0) { ir_node = create_ir_node(graph, tf_node->name.c_str(), op_load_map[tf_node->op].first, OP_VERSION); } @@ -1861,30 +1855,30 @@ int tensorflow_serializer::generate_graph(ir_graph_t* graph) { ir_node = get_ir_graph_node(graph, node_idx); } - for(int in = 0; in < tf_node->inputs.size(); in++) + for (int in = 0; in < tf_node->inputs.size(); in++) { TFNode* node = tf_node->inputs[in]; int tensor_idx = get_ir_tensor_index_from_name(graph, node->name.c_str()); ir_tensor_t* tensor = nullptr; - if(node->name == "Placeholder") + if (node->name == "Placeholder") { continue; } - if(tensor_idx < 0) - tensor = create_ir_tensor(graph, tf_node->name.c_str(),TENGINE_DT_FP32 ); + if (tensor_idx < 0) + tensor = create_ir_tensor(graph, tf_node->name.c_str(), TENGINE_DT_FP32); else tensor = get_ir_graph_tensor(graph, tensor_idx); set_ir_node_input_tensor(ir_node, in, tensor); input_tensors.push_back(node->name.c_str()); } - for(int out = 0; out < tf_node->outputs.size(); out++) + for (int out = 0; out < tf_node->outputs.size(); out++) { TFNode* node = tf_node->outputs[out]; int tensor_idx = get_ir_tensor_index_from_name(graph, node->name.c_str()); ir_tensor_t* tensor = nullptr; - if(tensor_idx < 0) - tensor = create_ir_tensor(graph, tf_node->name.c_str(),TENGINE_DT_FP32 ); + if (tensor_idx < 0) + tensor = create_ir_tensor(graph, tf_node->name.c_str(), TENGINE_DT_FP32); else tensor = get_ir_graph_tensor(graph, tensor_idx); set_ir_node_output_tensor(ir_node, out, tensor); @@ -1897,8 +1891,8 @@ int tensorflow_serializer::generate_graph(ir_graph_t* graph) fprintf(stderr, "load op %s func failed in node %s .\n", tf_node->op.c_str(), tf_node->name.c_str()); return -1; } - } - + } + // for(i = 0; i < (int)tf_graph.seq_nodes.size(); i++) // { // TFNode* tf_node = tf_graph.seq_nodes[i]; @@ -1906,7 +1900,6 @@ int tensorflow_serializer::generate_graph(ir_graph_t* graph) // if(tf_node->op == "Placeholder" || tf_node->op == "Const") // continue; - // op_load_t loader = op_load_map[tf_node->op].second; // // printf("%s \n", tf_node->op.c_str()); // if (loader(tf_node, tf_graph, graph) < 0) @@ -1917,7 +1910,7 @@ int tensorflow_serializer::generate_graph(ir_graph_t* graph) // } - if(i < node_number) + if (i < node_number) return -1; return 0; @@ -1944,11 +1937,11 @@ int tensorflow_serializer::set_graph_output(ir_graph_t* graph) { int tensor_id = get_ir_tensor_index_from_name(graph, graph_outputs[i].c_str()); ir_tensor_t* tensor = nullptr; - if(tensor_id < 0) - tensor = create_ir_tensor(graph, graph_outputs[i].c_str(),TENGINE_DT_FP32 ); + if (tensor_id < 0) + tensor = create_ir_tensor(graph, graph_outputs[i].c_str(), TENGINE_DT_FP32); else tensor = get_ir_graph_tensor(graph, tensor_id); - int node_idx = get_ir_node_index_from_name(graph,graph_outputs[i].c_str() ); + int node_idx = get_ir_node_index_from_name(graph, graph_outputs[i].c_str()); ir_node_t* node = get_ir_graph_node(graph, node_idx); set_ir_node_output_tensor(node, 0, tensor); output_nodes.push_back(node->index); @@ -1986,7 +1979,6 @@ int tensorflow_serializer::load_graph(ir_graph_t* graph) return 0; } - int tensorflow_serializer::load_model(ir_graph_t* graph, std::string model_file) { register_op_load(); @@ -2030,28 +2022,28 @@ int load_pool(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* const tensorflow::NodeDef* node_def = tf_node->pb_defs[0]; tensorflow::AttrValue value; - if(GetAttrValue(node_def, "ksize", value)) + if (GetAttrValue(node_def, "ksize", value)) { param->kernel_h = value.list().i(1); param->kernel_w = value.list().i(2); } - if(GetAttrValue(node_def, "strides", value)) + if (GetAttrValue(node_def, "strides", value)) { param->stride_h = value.list().i(1); param->stride_w = value.list().i(2); } - if(GetAttrValue(node_def, "padding", value)) + if (GetAttrValue(node_def, "padding", value)) { - if(value.s() == "VALID") + if (value.s() == "VALID") { param->pad_h0 = 0; param->pad_h1 = 0; param->pad_w0 = 0; param->pad_w1 = 0; } - else if(value.s() == "SAME") + else if (value.s() == "SAME") { param->pad_h0 = -1; param->pad_h1 = -1; @@ -2060,11 +2052,11 @@ int load_pool(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* } } - if(tf_node->op == "AvgPool") + if (tf_node->op == "AvgPool") { param->pool_method = 0; } - else if(tf_node->op == "MaxPool") + else if (tf_node->op == "MaxPool") { param->pool_method = 1; } @@ -2075,7 +2067,7 @@ int load_conv(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* TFNode* input0 = tf_node->inputs[0]; /* input */ TFNode* input1 = tf_node->inputs[1]; /* weight */ TFNode* input2 = nullptr; - if(tf_node->inputs.size() > 2) + if (tf_node->inputs.size() > 2) { input2 = tf_node->inputs[2]; } @@ -2083,21 +2075,21 @@ int load_conv(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* struct conv_param* param = (struct conv_param*)node->op.param_mem; tensorflow::AttrValue value; - if(GetAttrValue(node_def, "dilations", value)) + if (GetAttrValue(node_def, "dilations", value)) { param->dilation_h = value.list().i(1); param->dilation_w = value.list().i(2); } - if(GetAttrValue(node_def, "padding", value)) + if (GetAttrValue(node_def, "padding", value)) { - if(value.s() == "VALID") + if (value.s() == "VALID") { param->pad_h0 = 0; param->pad_h1 = 0; param->pad_w0 = 0; param->pad_w1 = 0; } - else if(value.s() == "SAME") + else if (value.s() == "SAME") { param->pad_h0 = -1; param->pad_h1 = -1; @@ -2106,7 +2098,7 @@ int load_conv(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* } } - if(GetAttrValue(node_def, "strides", value)) + if (GetAttrValue(node_def, "strides", value)) { param->stride_h = value.list().i(1); param->stride_w = value.list().i(2); @@ -2118,18 +2110,18 @@ int load_conv(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* const tensorflow::NodeDef* weight_def = input1->pb_defs[0]; - if(GetAttrValue(weight_def, "value", value)) + if (GetAttrValue(weight_def, "value", value)) { const tensorflow::TensorShapeProto& shape = value.tensor().tensor_shape(); - if(shape.dim_size() == 4) + if (shape.dim_size() == 4) { kernel_h = shape.dim(0).size(); kernel_w = shape.dim(1).size(); in_channel = shape.dim(2).size(); out_channel = shape.dim(3).size(); } - else if(shape.dim_size() == 3) + else if (shape.dim_size() == 3) { kernel_h = 1; kernel_w = shape.dim(0).size(); @@ -2140,31 +2132,31 @@ int load_conv(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* ir_tensor_t* weight_tensor = input1->ir_tensor; int elem_size = out_channel * in_channel * kernel_h * kernel_w; - float* new_weight = ( float* )malloc(sizeof(float) * elem_size); + float* new_weight = (float*)malloc(sizeof(float) * elem_size); float* src = (float*)weight_tensor->data; - weight_tensor->data = sys_malloc(elem_size*sizeof(float)); + weight_tensor->data = sys_malloc(elem_size * sizeof(float)); float* ptr = (float*)weight_tensor->data; - for(int o = 0; o < out_channel; o++) - for(int h = 0; h < kernel_h; h++) - for(int w = 0; w < kernel_w; w++) - for(int i = 0; i < in_channel; i++) + for (int o = 0; o < out_channel; o++) + for (int h = 0; h < kernel_h; h++) + for (int w = 0; w < kernel_w; w++) + for (int i = 0; i < in_channel; i++) { - ptr[o*in_channel*kernel_h*kernel_w + i*kernel_h*kernel_w + h*kernel_w + w] - = src[h * (kernel_w * in_channel * out_channel) + w * (in_channel * out_channel) + i * out_channel + o]; + ptr[o * in_channel * kernel_h * kernel_w + i * kernel_h * kernel_w + h * kernel_w + w] + = src[h * (kernel_w * in_channel * out_channel) + w * (in_channel * out_channel) + i * out_channel + o]; } free(src); weight_tensor->tensor_type = TENSOR_TYPE_CONST; - if(tf_node->op == "DepthwiseConv2dNative") + if (tf_node->op == "DepthwiseConv2dNative") { group = in_channel; out_channel = in_channel * out_channel; in_channel = 1; } - int* dims = (int*)malloc(sizeof(int)*4); + int* dims = (int*)malloc(sizeof(int) * 4); dims[0] = out_channel; dims[1] = in_channel; dims[2] = kernel_h; @@ -2187,8 +2179,7 @@ int load_conv(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* param->output_channel = out_channel; param->group = group; - - if(tf_node->op == "DepthwiseConv2dNative") + if (tf_node->op == "DepthwiseConv2dNative") { in_channel = group; out_channel = out_channel / in_channel; @@ -2196,28 +2187,27 @@ int load_conv(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* int pb_def_num = tf_node->pb_defs.size(); - if(pb_def_num > 1) + if (pb_def_num > 1) { // the last one, const tensorflow::NodeDef* node_def = tf_node->pb_defs[pb_def_num - 1]; /* possible pad */ - if(node_def->op() == "Const") + if (node_def->op() == "Const") { tensorflow::AttrValue value; - if(GetAttrValue(node_def, "value", value) && value.has_tensor()) + if (GetAttrValue(node_def, "value", value) && value.has_tensor()) { const tensorflow::TensorProto& tf_tensor = value.tensor(); int dim_size = tf_tensor.tensor_shape().dim_size(); - if(dim_size == 2 && tf_tensor.tensor_shape().dim(0).size() == 4 && - tf_tensor.tensor_shape().dim(1).size() == 2) + if (dim_size == 2 && tf_tensor.tensor_shape().dim(0).size() == 4 && tf_tensor.tensor_shape().dim(1).size() == 2) { std::vector shape_data(8); - if(tf_tensor.tensor_content().size()) + if (tf_tensor.tensor_content().size()) { // int* dst = shape_data.data(); memcpy(ptr, tf_tensor.tensor_content().c_str(), tf_tensor.tensor_content().size()); @@ -2226,7 +2216,7 @@ int load_conv(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* { int data_num = tf_tensor.int_val_size(); - for(int i = 0; i < data_num; i++) + for (int i = 0; i < data_num; i++) { shape_data[i] = tf_tensor.int_val(i); } @@ -2238,7 +2228,6 @@ int load_conv(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* /* w pad */ param->pad_w0 = shape_data[4]; param->pad_w1 = shape_data[5]; - } } } @@ -2251,7 +2240,7 @@ int load_batchnorm(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_nod const tensorflow::NodeDef* node_def = tf_node->pb_defs[0]; tensorflow::AttrValue value; - if(GetAttrValue(node_def, "epsilon", value)) + if (GetAttrValue(node_def, "epsilon", value)) { param->eps = value.f(); } diff --git a/tools/convert_tool/tensorflow/tf2tengine.hpp b/tools/convert_tool/tensorflow/tf2tengine.hpp index 00505fb74..00199738e 100644 --- a/tools/convert_tool/tensorflow/tf2tengine.hpp +++ b/tools/convert_tool/tensorflow/tf2tengine.hpp @@ -55,12 +55,10 @@ extern "C" { #include "save_graph/op_include.h" } - -#define TF_RNN_LSTM 0 -#define TF_RNN_GRU 1 +#define TF_RNN_LSTM 0 +#define TF_RNN_GRU 1 #define TF_RNN_BASIC_LSTM 2 -#define TF_RNN_BASIC_RNN 3 - +#define TF_RNN_BASIC_RNN 3 struct TFNode { @@ -80,7 +78,9 @@ struct TFNode no_static_node = false; } - virtual ~TFNode() {} + virtual ~TFNode() + { + } }; struct LSTMNode : public TFNode @@ -120,9 +120,9 @@ struct LSTMNode : public TFNode auto rnn_ir = rnn_graph.begin(); auto rnn_end = rnn_graph.end(); - while(rnn_ir != rnn_end) + while (rnn_ir != rnn_end) { - delete(*rnn_ir); + delete (*rnn_ir); rnn_ir++; } } @@ -153,9 +153,9 @@ struct RNNNode : public TFNode auto rnn_ir = rnn_graph.begin(); auto rnn_end = rnn_graph.end(); - while(rnn_ir != rnn_end) + while (rnn_ir != rnn_end) { - delete(*rnn_ir); + delete (*rnn_ir); rnn_ir++; } } @@ -195,9 +195,9 @@ struct GRUNode : public TFNode auto rnn_ir = rnn_graph.begin(); auto rnn_end = rnn_graph.end(); - while(rnn_ir != rnn_end) + while (rnn_ir != rnn_end) { - delete(*rnn_ir); + delete (*rnn_ir); rnn_ir++; } } @@ -209,12 +209,11 @@ struct TFGraph ~TFGraph() { - for(auto node : seq_nodes) + for (auto node : seq_nodes) delete node; } }; - class tensorflow_serializer { public: @@ -239,7 +238,7 @@ class tensorflow_serializer int FindRNNScope(std::string& rnn_scope); void ParseLSTMGraph(LSTMNode* lstm_node, std::set& rnn_graph); void StripRNNScope(std::string& rnn_scope, int rnn_type); - void MergeReluMinimum(); + void MergeReluMinimum(); int MergeChildNode(TFNode* base_node, TFNode* child_node); int MergeParentNode(TFNode* base_node, TFNode* child_node); int BNRecursiveInputMerge(TFNode* node); From e7a95ed926177b809a0330a389782d16667448f5 Mon Sep 17 00:00:00 2001 From: bzhang Date: Fri, 20 Aug 2021 15:13:18 +0800 Subject: [PATCH 4/8] suppoer tensorflow mobilenet --- tools/convert_tool/tensorflow/tf2tengine.cpp | 868 +++++++++++-------- 1 file changed, 505 insertions(+), 363 deletions(-) diff --git a/tools/convert_tool/tensorflow/tf2tengine.cpp b/tools/convert_tool/tensorflow/tf2tengine.cpp index 34cb2c000..4641665fa 100644 --- a/tools/convert_tool/tensorflow/tf2tengine.cpp +++ b/tools/convert_tool/tensorflow/tf2tengine.cpp @@ -53,7 +53,7 @@ static bool GetAttrValue(const tensorflow::NodeDef* node, const char* key, tenso const google::protobuf::Map& attr = node->attr(); const google::protobuf::Map::const_iterator it = attr.find(key); - if (it != attr.end()) + if(it != attr.end()) { value = it->second; return true; @@ -63,18 +63,15 @@ static bool GetAttrValue(const tensorflow::NodeDef* node, const char* key, tenso } int GetTensorContentAndDim(const tensorflow::TensorProto& tf_tensor, int** dims, void** mem_ptr, - std::string& layout) + std::string& layout) { const tensorflow::TensorShapeProto& shape = tf_tensor.tensor_shape(); int elem_num = 1; int dim_num = shape.dim_size(); - int* dim_tmp = (int*)malloc(sizeof(int) * dim_num); - - // printf("dim num : %d \n", dim_num); - // dims = (int*)malloc(sizeof(int)*dim_num); - for (int i = 0; i < dim_num; i++) + int* dim_tmp = (int*)malloc(sizeof(int)*dim_num); + for(int i = 0; i < dim_num; i++) { elem_num *= shape.dim(i).size(); dim_tmp[i] = shape.dim(i).size(); @@ -82,22 +79,22 @@ int GetTensorContentAndDim(const tensorflow::TensorProto& tf_tensor, int** dims, void* mem_buf = nullptr; - if (tf_tensor.tensor_content().size()) + if(tf_tensor.tensor_content().size()) { int content_size = tf_tensor.tensor_content().size(); mem_buf = malloc(content_size + 128); - void* src = (void*)tf_tensor.tensor_content().c_str(); + void* src = ( void* )tf_tensor.tensor_content().c_str(); memcpy(mem_buf, src, content_size); } - else if (tf_tensor.dtype() == tensorflow::DataType::DT_FLOAT) + else if(tf_tensor.dtype() == tensorflow::DataType::DT_FLOAT) { // in packed format int data_num = tf_tensor.float_val_size(); mem_buf = malloc(elem_num * sizeof(float)); - float* mem = (float*)mem_buf; - if (data_num >= elem_num) + float* mem = ( float* )mem_buf; + if(data_num >= elem_num) { - for (int i = 0; i < elem_num; i++) + for(int i = 0; i < elem_num; i++) { mem[i] = tf_tensor.float_val(i); } @@ -105,28 +102,28 @@ int GetTensorContentAndDim(const tensorflow::TensorProto& tf_tensor, int** dims, else { // data_num < elem_num - for (int i = 0; i < data_num; i++) + for(int i = 0; i < data_num; i++) { mem[i] = tf_tensor.float_val(i); } - for (int i = data_num; i < elem_num; i++) + for(int i = data_num; i < elem_num; i++) { mem[i] = mem[data_num - 1]; } } } - else if (tf_tensor.dtype() == tensorflow::DataType::DT_INT32) + else if(tf_tensor.dtype() == tensorflow::DataType::DT_INT32) { int data_num = tf_tensor.int_val_size(); mem_buf = malloc(elem_num * sizeof(int)); - int* mem = (int*)mem_buf; + int* mem = ( int* )mem_buf; - if (data_num >= elem_num) + if(data_num >= elem_num) { - for (int i = 0; i < elem_num; i++) + for(int i = 0; i < elem_num; i++) { mem[i] = tf_tensor.int_val(i); } @@ -134,12 +131,12 @@ int GetTensorContentAndDim(const tensorflow::TensorProto& tf_tensor, int** dims, else { // data_num < elem_num - for (int i = 0; i < data_num; i++) + for(int i = 0; i < data_num; i++) { mem[i] = tf_tensor.int_val(i); } - for (int i = data_num; i < elem_num; i++) + for(int i = data_num; i < elem_num; i++) { mem[i] = mem[data_num - 1]; } @@ -148,22 +145,22 @@ int GetTensorContentAndDim(const tensorflow::TensorProto& tf_tensor, int** dims, *mem_ptr = mem_buf; *dims = dim_tmp; - switch (dim_num) - { - case 0: - layout = "W"; - break; - case 1: - layout = "W"; - break; - case 2: - layout = "HW"; - break; - case 4: - layout = "NCHW"; - break; - default: - break; + switch(dim_num) + { + case 0: + layout = "W"; + break; + case 1: + layout = "W"; + break; + case 2: + layout = "HW"; + break; + case 4: + layout = "NCHW"; + break; + default: + break; } return dim_num; } @@ -171,7 +168,7 @@ int tensorflow_serializer::load_binary_file(std::string model_file) { std::ifstream is(model_file.c_str(), std::ios::in | std::ios::binary); - if (!is.is_open()) + if(!is.is_open()) { TLOG_ERR("cannot open file: %s \n", model_file.c_str()); return false; @@ -189,9 +186,9 @@ int tensorflow_serializer::load_binary_file(std::string model_file) is.close(); - if (!ret) + if(!ret) { - TLOG_ERR("parse file: %s failed\n", model_file.c_str()); + TLOG_ERR( "parse file: %s failed\n",model_file.c_str()); return -1; } return ret; @@ -199,27 +196,27 @@ int tensorflow_serializer::load_binary_file(std::string model_file) int load_const_tensor(TFNode* tf_node, ir_graph_t* graph) { ir_node_t* node = create_ir_node(graph, tf_node->name.c_str(), OP_CONST, OP_VERSION); - ir_tensor_t* tensor = create_ir_tensor(graph, tf_node->name.c_str(), TENGINE_DT_FP32); + ir_tensor_t* tensor = create_ir_tensor(graph, tf_node->name.c_str(),TENGINE_DT_FP32); tensorflow::AttrValue value; const tensorflow::NodeDef* node_def = tf_node->pb_defs[0]; - if (GetAttrValue(node_def, "value", value)) + if(GetAttrValue(node_def, "value", value)) { const tensorflow::TensorProto& tf_tensor = value.tensor(); void* mem_ptr; - int* dims; + int* dims ; std::string layout; int dim_num = GetTensorContentAndDim(tf_tensor, &dims, &mem_ptr, layout); set_ir_tensor_shape(tensor, dims, dim_num); int mem_size = 1; - for (int i = 0; i < dim_num; i++) + for(int i = 0; i < dim_num; i++) mem_size *= dims[i]; - tensor->data = (float*)malloc(sizeof(float) * mem_size); + tensor->data = (float*)malloc(sizeof(float)*mem_size); tensor->tensor_type = TENSOR_TYPE_CONST; float* tmp = (float*)mem_ptr; float* tr_tmp = (float*)tensor->data; - for (int i = 0; i < mem_size; i++) + for(int i = 0; i < mem_size; i++) { tr_tmp[i] = tmp[i]; } @@ -233,25 +230,25 @@ int tensorflow_serializer::set_graph_input(ir_graph_t* graph) { int node_num = tf_graph.seq_nodes.size(); std::vector input_nodes; - for (int i = 0; i < node_num; i++) + for(int i = 0; i < node_num; i++) { - TFNode* tf_node = tf_graph.seq_nodes[i]; - if (tf_node->op == "Placeholder") + TFNode* tf_node =tf_graph.seq_nodes[i]; + if(tf_node->op == "Placeholder") { ir_tensor_t* ir_tensor = create_ir_tensor(graph, tf_node->name.c_str(), TENGINE_DT_FP32); tensorflow::AttrValue shape; int pb_defs_cnt = tf_node->pb_defs.size(); int* dims; - if (pb_defs_cnt == 1) + if(pb_defs_cnt == 1) { - if (GetAttrValue(tf_node->pb_defs[0], "shape", shape)) + if(GetAttrValue(tf_node->pb_defs[0], "shape", shape)) { int dim_size = shape.shape().dim_size(); - + dims = (int*)sys_malloc(dim_size); - memset(dims, 0, sizeof(int) * dim_size); - for (int i = 0; i < dim_size; ++i) + memset(dims, 0, sizeof(int)*dim_size); + for(int i = 0; i < dim_size; ++i) { dims[i] = shape.shape().dim(i).size(); } @@ -269,7 +266,7 @@ int tensorflow_serializer::set_graph_input(ir_graph_t* graph) { tensorflow::AttrValue value; const tensorflow::NodeDef* node_def = tf_node->pb_defs[pb_defs_cnt - 1]; - if (GetAttrValue(node_def, "value", value)) + if(GetAttrValue(node_def, "value", value)) { const tensorflow::TensorProto& tf_tensor = value.tensor(); @@ -279,32 +276,32 @@ int tensorflow_serializer::set_graph_input(ir_graph_t* graph) int dim_num = GetTensorContentAndDim(tf_tensor, &dims, &mem_ptr, layout); int mem_size = 1; - for (int i = 0; i < dim_num; i++) + for(int i = 0; i < dim_num; i++) mem_size *= dims[i]; - ir_tensor->data = (float*)malloc(sizeof(float) * mem_size); + ir_tensor->data = (float*)malloc(sizeof(float)*mem_size); ir_tensor->tensor_type = TENSOR_TYPE_CONST; // tensor->data = mem_ptr; float* tmp = (float*)mem_ptr; float* tr_tmp = (float*)ir_tensor->data; - for (int i = 0; i < mem_size; i++) + for(int i = 0; i < mem_size; i++) tr_tmp[i] = tmp[i]; - int* reshape_dim = (int*)mem_ptr; - for (int i = 0; i < tf_dims[0]; i++) + int* reshape_dim = ( int* )mem_ptr; + for(int i = 0; i < tf_dims[0]; i++) { dims[i] = reshape_dim[i]; } - for (unsigned int i = 0; i < tf_dims[0]; i++) + for(unsigned int i = 0; i < tf_dims[0]; i++) { - if (dims[i] == -1) + if(dims[i] == -1) dims[i] = 1; } free(mem_ptr); set_ir_tensor_shape(ir_tensor, dims, tf_dims[0]); } } - ir_node_t* node = create_ir_node(graph, tf_node->name.c_str(), OP_INPUT, OP_VERSION); + ir_node_t* node = create_ir_node(graph, tf_node->name.c_str(), OP_INPUT, OP_VERSION); int tensor_id = get_ir_tensor_index_from_name(graph, tf_node->name.c_str()); @@ -326,7 +323,7 @@ int tensorflow_serializer::construct_graph() std::unordered_map node_map; /* first scan, setup all nodes */ - for (int i = 0; i < node_number; i++) + for(int i = 0; i < node_number; i++) { const tensorflow::NodeDef& node_param = tf_net.node(i); @@ -343,30 +340,30 @@ int tensorflow_serializer::construct_graph() } /* the second scan, setup connections */ - for (int i = 0; i < node_number; i++) + for(int i = 0; i < node_number; i++) { const tensorflow::NodeDef& node_param = tf_net.node(i); const std::string& name = node_param.name(); TFNode* cur_node = node_map[name]; - for (int j = 0; j < node_param.input_size(); j++) + for(int j = 0; j < node_param.input_size(); j++) { const std::string& input_name = node_param.input(j); std::string::size_type pos = input_name.find(":"); std::string cleanup_name; - if (pos == std::string::npos) + if(pos == std::string::npos) pos = input_name.size(); - if (input_name[0] == '^') + if(input_name[0] == '^') cleanup_name = input_name.substr(1, pos); else cleanup_name = input_name.substr(0, pos); TFNode* input_node = node_map[cleanup_name]; - if (input_node == nullptr) + if(input_node == nullptr) { TLOG_ERR("cannot find input: %s for node: %s \n", input_name.c_str(), name.c_str()); return false; @@ -382,21 +379,21 @@ int DisconnectNode(TFNode* cur_node) { TFNode* input_node; - for (unsigned int i = 0; i < cur_node->inputs.size(); i++) + for(unsigned int i = 0; i < cur_node->inputs.size(); i++) { input_node = cur_node->inputs[i]; auto ir = input_node->outputs.begin(); - while (ir != input_node->outputs.end()) + while(ir != input_node->outputs.end()) { - if (*ir != cur_node) + if(*ir != cur_node) ir++; else break; } - if (ir == input_node->outputs.end()) + if(ir == input_node->outputs.end()) { TLOG_ERR("ERROR on node connection!!\n"); } @@ -408,21 +405,21 @@ int DisconnectNode(TFNode* cur_node) TFNode* output_node; - for (unsigned int i = 0; i < cur_node->outputs.size(); i++) + for(unsigned int i = 0; i < cur_node->outputs.size(); i++) { output_node = cur_node->outputs[i]; auto ir = output_node->inputs.begin(); - while (ir != output_node->inputs.end()) + while(ir != output_node->inputs.end()) { - if (*ir != cur_node) + if(*ir != cur_node) ir++; else break; } - if (ir == output_node->inputs.end()) + if(ir == output_node->inputs.end()) { TLOG_ERR("ERROR on node connection!!\n"); } @@ -439,15 +436,15 @@ int tensorflow_serializer::MergeParentNode(TFNode* base_node, TFNode* parent_nod auto input_ir = base_node->inputs.begin(); - while (input_ir != base_node->inputs.end()) + while(input_ir != base_node->inputs.end()) { - if (*input_ir == parent_node) + if(*input_ir == parent_node) break; input_ir++; } - if (parent_node->inputs.size() == 1) + if(parent_node->inputs.size() == 1) { *input_ir = parent_node->inputs[0]; } @@ -461,11 +458,11 @@ int tensorflow_serializer::MergeParentNode(TFNode* base_node, TFNode* parent_nod /* setup the outputs of parent node's parent */ - for (auto node : parent_node->inputs) + for(auto node : parent_node->inputs) { - for (unsigned int i = 0; i < node->outputs.size(); i++) + for(unsigned int i = 0; i < node->outputs.size(); i++) { - if (node->outputs[i] == parent_node) + if(node->outputs[i] == parent_node) { node->outputs[i] = base_node; break; @@ -477,17 +474,17 @@ int tensorflow_serializer::MergeParentNode(TFNode* base_node, TFNode* parent_nod auto output_ir = parent_node->outputs.begin(); - while (output_ir != parent_node->outputs.end()) + while(output_ir != parent_node->outputs.end()) { TFNode* node = *output_ir; - if (node != base_node) + if(node != base_node) { base_node->outputs.push_back(node); - for (unsigned int i = 0; i < node->inputs.size(); i++) + for(unsigned int i = 0; i < node->inputs.size(); i++) { - if (node->inputs[i] == parent_node) + if(node->inputs[i] == parent_node) { node->inputs[i] = base_node; break; @@ -512,19 +509,19 @@ int tensorflow_serializer::MergeParentNode(TFNode* base_node, TFNode* parent_nod bool CheckComposedBNAdd(TFNode* cur_node) { - if (cur_node->op != "Add") + if(cur_node->op != "Add") return false; TFNode* input0 = cur_node->inputs[0]; TFNode* input1 = cur_node->inputs[1]; - if (input0->op != "Mul" || input1->op != "Sub") + if(input0->op != "Mul" || input1->op != "Sub") return false; /* further check: /add_1 int name */ - if (cur_node->name.find("/add_1") != std::string::npos) + if(cur_node->name.find("/add_1") != std::string::npos) { - if (input0->name.find("/mul_1") != std::string::npos || input1->name.find("/mul_1") != std::string::npos) + if(input0->name.find("/mul_1") != std::string::npos || input1->name.find("/mul_1") != std::string::npos) cur_node->BNAddType = 1; else cur_node->BNAddType = 0; @@ -539,20 +536,20 @@ int tensorflow_serializer::BNRecursiveInputMerge(TFNode* node) { bool mul_1_node = false; bool mul_node = false; - if (node->name.find("/mul") != std::string::npos) + if(node->name.find("/mul") != std::string::npos) { - if (node->BNAddType == 1) + if(node->BNAddType == 1) { - if (node->name.find("/mul_1") != std::string::npos) + if(node->name.find("/mul_1") != std::string::npos) { mul_1_node = true; } - else if (node->name.find("/mul_2") == std::string::npos) + else if(node->name.find("/mul_2") == std::string::npos) { // disconnect the connection between mul and mul2 auto ir = node->outputs.begin(); - if ((*ir)->name.find("/mul2") == std::string::npos) + if((*ir)->name.find("/mul2") == std::string::npos) ir++; TFNode* mul2_node = *ir; @@ -561,7 +558,7 @@ int tensorflow_serializer::BNRecursiveInputMerge(TFNode* node) ir = mul2_node->inputs.begin(); - if ((*ir)->name.find("/mul") == std::string::npos) + if((*ir)->name.find("/mul") == std::string::npos) ir++; mul2_node->inputs.erase(ir); @@ -569,15 +566,15 @@ int tensorflow_serializer::BNRecursiveInputMerge(TFNode* node) } else { - if (node->name.find("/mul_1") != std::string::npos) + if(node->name.find("/mul_1") != std::string::npos) { // disconnect the connection between add_1 mul_1 auto ir = node->inputs.begin(); - if ((*ir)->name.find("/add_1") == std::string::npos) + if((*ir)->name.find("/add_1") == std::string::npos) ir++; - if ((*ir)->name.find("/add_1") != std::string::npos) + if((*ir)->name.find("/add_1") != std::string::npos) { TFNode* Rsqrt_node = *ir; @@ -585,7 +582,7 @@ int tensorflow_serializer::BNRecursiveInputMerge(TFNode* node) ir = Rsqrt_node->outputs.begin(); - if ((*ir)->name.find("/mul_1") == std::string::npos) + if((*ir)->name.find("/mul_1") == std::string::npos) ir++; Rsqrt_node->outputs.erase(ir); @@ -594,7 +591,6 @@ int tensorflow_serializer::BNRecursiveInputMerge(TFNode* node) else { mul_node = true; - // printf("name:%s\n",node->name.c_str()); } } } @@ -602,16 +598,16 @@ int tensorflow_serializer::BNRecursiveInputMerge(TFNode* node) int orig_input_size = node->inputs.size(); std::vector input_cpy = node->inputs; - for (int i = 0; i < orig_input_size; i++) + for(int i = 0; i < orig_input_size; i++) { - if (mul_node && i == 0) + if(mul_node && i == 0) continue; - if (mul_1_node && i == 0) + if(mul_1_node && i == 0) continue; TFNode* input_node = input_cpy[i]; input_node->BNAddType = node->BNAddType; - if (input_node->op == "Const") + if(input_node->op == "Const") continue; BNRecursiveInputMerge(input_node); @@ -629,11 +625,11 @@ int tensorflow_serializer::FuseComposedBN(TFNode* cur_node) /* skip to create static node for add/y */ - for (unsigned int i = 0; i < cur_node->inputs.size(); i++) + for(unsigned int i = 0; i < cur_node->inputs.size(); i++) { TFNode* node = cur_node->inputs[i]; - if (node->name.find("/add/y") != std::string::npos) + if(node->name.find("/add/y") != std::string::npos) node->no_static_node = true; } } @@ -641,14 +637,14 @@ int tensorflow_serializer::MergeChildNode(TFNode* base_node, TFNode* child_node) { auto output_ir = base_node->outputs.begin(); - while (output_ir != base_node->outputs.end()) + while(output_ir != base_node->outputs.end()) { - if (*output_ir == child_node) + if(*output_ir == child_node) break; output_ir++; } - if (child_node->outputs.size() == 1) + if(child_node->outputs.size() == 1) { *output_ir = child_node->outputs[0]; } @@ -658,11 +654,11 @@ int tensorflow_serializer::MergeChildNode(TFNode* base_node, TFNode* child_node) base_node->outputs.insert(base_node->outputs.end(), child_node->outputs.begin(), child_node->outputs.end()); } - for (auto node : child_node->outputs) + for(auto node : child_node->outputs) { - for (unsigned int i = 0; i < node->inputs.size(); i++) + for(unsigned int i = 0; i < node->inputs.size(); i++) { - if (node->inputs[i] == child_node) + if(node->inputs[i] == child_node) { node->inputs[i] = base_node; break; @@ -672,17 +668,17 @@ int tensorflow_serializer::MergeChildNode(TFNode* base_node, TFNode* child_node) auto ir = child_node->inputs.begin(); - while (ir != child_node->inputs.end()) + while(ir != child_node->inputs.end()) { TFNode* node = *ir; - if (node != base_node) + if(node != base_node) { base_node->inputs.push_back(node); - for (unsigned int i = 0; i < node->outputs.size(); i++) + for(unsigned int i = 0; i < node->outputs.size(); i++) { - if (node->outputs[i] == child_node) + if(node->outputs[i] == child_node) { node->outputs[i] = base_node; break; @@ -703,24 +699,25 @@ int tensorflow_serializer::MergeChildNode(TFNode* base_node, TFNode* child_node) return 0; } + void tensorflow_serializer::CleanupResizeNearestNeighbor() { auto ir = tf_graph.seq_nodes.begin(); - while (ir != tf_graph.seq_nodes.end()) + while(ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if (cur_node->op == "ResizeNearestNeighbor") + if(cur_node->op == "ResizeNearestNeighbor") { TFNode* data_node = cur_node->inputs[0]; TFNode* data_shape_node = nullptr; - for (unsigned int i = 0; i < data_node->outputs.size(); i++) + for(unsigned int i = 0; i < data_node->outputs.size(); i++) { data_shape_node = data_node->outputs[i]; - if (data_shape_node->op == "Shape") + if(data_shape_node->op == "Shape") break; } @@ -736,18 +733,19 @@ void tensorflow_serializer::CleanupResizeNearestNeighbor() } } + void tensorflow_serializer::MergeReluMinimum() { - for (auto ir = tf_graph.seq_nodes.begin(); ir != tf_graph.seq_nodes.end(); ir++) + for(auto ir = tf_graph.seq_nodes.begin(); ir != tf_graph.seq_nodes.end(); ir++) { TFNode* cur_node = *ir; - if (cur_node->inputs.size() == 0) + if(cur_node->inputs.size() == 0) continue; TFNode* input0 = cur_node->inputs[0]; - if (cur_node->op == "Minimum" && input0->op == "Relu") + if(cur_node->op == "Minimum" && input0->op == "Relu") { TFNode* const_node = cur_node->inputs[1]; @@ -765,18 +763,18 @@ int tensorflow_serializer::optimize_graph() /* first clean up the predictions module of TF */ auto ir = tf_graph.seq_nodes.begin(); - while (ir != tf_graph.seq_nodes.end()) + while(ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if (cur_node->op == "Reshape") + if(cur_node->op == "Reshape") { /* Reshape should have two inputs */ TFNode* input_node0 = cur_node->inputs[0]; TFNode* input_node1 = cur_node->inputs[1]; - if (input_node0->op == "Softmax" || input_node1->op == "Softmax") + if(input_node0->op == "Softmax" || input_node1->op == "Softmax") { DisconnectNode(cur_node); ir = tf_graph.seq_nodes.erase(ir); @@ -785,16 +783,16 @@ int tensorflow_serializer::optimize_graph() } TFNode* output_node = cur_node->outputs[0]; - if (NULL == output_node) + if(NULL == output_node) continue; - if (output_node->op == "Softmax" || output_node->op == "MatMul") + if(output_node->op == "Softmax" || output_node->op == "MatMul") { TFNode* input_node0 = cur_node->inputs[0]; TFNode* input_node1 = cur_node->inputs[1]; TFNode* input_node; - if (input_node0->op == "Const") + if(input_node0->op == "Const") { DisconnectNode(input_node0); input_node = input_node1; @@ -819,26 +817,26 @@ int tensorflow_serializer::optimize_graph() /* remove the squeeze node and identity */ ir = tf_graph.seq_nodes.begin(); - while (ir != tf_graph.seq_nodes.end()) + while(ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if (cur_node->op == "Squeeze") + if(cur_node->op == "Squeeze") { TFNode* softmax_node = nullptr; TFNode* shape_node = nullptr; - for (unsigned int j = 0; j < cur_node->outputs.size(); j++) + for(unsigned int j = 0; j < cur_node->outputs.size(); j++) { - if (cur_node->outputs[j]->op == "Softmax") + if(cur_node->outputs[j]->op == "Softmax") softmax_node = cur_node->outputs[j]; - else if (cur_node->outputs[j]->op == "Shape") + else if(cur_node->outputs[j]->op == "Shape") shape_node = cur_node->outputs[j]; } - if (softmax_node) + if(softmax_node) { - if (shape_node) + if(shape_node) DisconnectNode(shape_node); TFNode* input_node = cur_node->inputs[0]; @@ -848,7 +846,7 @@ int tensorflow_serializer::optimize_graph() continue; } - if (cur_node->outputs.size() == 1 && softmax_node == nullptr) + if(cur_node->outputs.size() == 1 && softmax_node == nullptr) { TFNode* child_node = cur_node->outputs[0]; @@ -859,7 +857,7 @@ int tensorflow_serializer::optimize_graph() } } - if (cur_node->op == "Identity") + if(cur_node->op == "Identity") { TFNode* input_node = cur_node->inputs[0]; MergeChildNode(input_node, cur_node); @@ -869,22 +867,22 @@ int tensorflow_serializer::optimize_graph() continue; } - if (cur_node->op == "ConcatV2") + if(cur_node->op == "ConcatV2") { TFNode* axis_node = nullptr; - for (unsigned int i = 0; i < cur_node->inputs.size(); i++) + for(unsigned int i = 0; i < cur_node->inputs.size(); i++) { TFNode* check_node = cur_node->inputs[i]; - if (check_node->op == "Const") + if(check_node->op == "Const") { axis_node = check_node; break; } } - if (axis_node) + if(axis_node) { cur_node->pb_defs.push_back(axis_node->pb_defs[0]); DisconnectNode(axis_node); @@ -898,15 +896,15 @@ int tensorflow_serializer::optimize_graph() ir = tf_graph.seq_nodes.begin(); - while (ir != tf_graph.seq_nodes.end()) + while(ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if (cur_node->op == "FIFOQueueV2") + if(cur_node->op == "FIFOQueueV2") { TFNode* queue_node = cur_node->outputs[0]; - if (queue_node->op == "QueueDequeueManyV2") + if(queue_node->op == "QueueDequeueManyV2") { MergeParentNode(queue_node, queue_node->inputs[1]); } @@ -922,16 +920,16 @@ int tensorflow_serializer::optimize_graph() /* remove ExpandDims */ ir = tf_graph.seq_nodes.begin(); - while (ir != tf_graph.seq_nodes.end()) + while(ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if (cur_node->op == "ExpandDims") + if(cur_node->op == "ExpandDims") { TFNode* input0 = cur_node->inputs[0]; TFNode* input1 = cur_node->inputs[1]; - if (input0->op == "Constant" && input1->op == "Const") + if(input0->op == "Constant" && input1->op == "Const") { TFNode* input1 = cur_node->inputs[1]; TFNode* child_node = cur_node->outputs[0]; @@ -944,7 +942,7 @@ int tensorflow_serializer::optimize_graph() } else { - if (input1->op == "Const") + if(input1->op == "Const") DisconnectNode(input1); else DisconnectNode(input0); @@ -966,15 +964,15 @@ int tensorflow_serializer::optimize_graph() /* merge biasadd and conv */ ir = tf_graph.seq_nodes.begin(); - while (ir != tf_graph.seq_nodes.end()) + while(ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if (cur_node->op == "Conv2D" || cur_node->op == "DepthwiseConv2dNative" || cur_node->op == "MatMul") + if(cur_node->op == "Conv2D" || cur_node->op == "DepthwiseConv2dNative" || cur_node->op == "MatMul") { TFNode* output_node = cur_node->outputs[0]; - if (output_node->op == "BiasAdd" || output_node->op == "Add") + if(output_node->op == "BiasAdd" || output_node->op == "Add") { MergeChildNode(cur_node, output_node); } @@ -987,11 +985,11 @@ int tensorflow_serializer::optimize_graph() ir = tf_graph.seq_nodes.begin(); - while (ir != tf_graph.seq_nodes.end()) + while(ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if (CheckComposedBNAdd(cur_node)) + if(CheckComposedBNAdd(cur_node)) FuseComposedBN(cur_node); ir++; } @@ -1004,21 +1002,21 @@ int tensorflow_serializer::optimize_graph() MergeReluMinimum(); /* merge input node and reshape */ ir = tf_graph.seq_nodes.begin(); - while (ir != tf_graph.seq_nodes.end()) + while(ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if (cur_node->op == "Reshape") + if(cur_node->op == "Reshape") { /* Reshape should have two inputs */ TFNode* input_node0 = cur_node->inputs[0]; TFNode* input_node1 = cur_node->inputs[1]; - if (input_node0->op == "Placeholder" || input_node1->op == "Placeholder") + if(input_node0->op == "Placeholder" || input_node1->op == "Placeholder") { TFNode* input_node; TFNode* const_node; - if (input_node0->op == "Const") + if(input_node0->op == "Const") { const_node = input_node0; input_node = input_node1; @@ -1045,15 +1043,15 @@ int tensorflow_serializer::optimize_graph() ir = tf_graph.seq_nodes.begin(); - while (ir != tf_graph.seq_nodes.end()) + while(ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if (cur_node->op == "StridedSlice") + if(cur_node->op == "StridedSlice") { /* check if input0 is "shape" */ TFNode* input_node = cur_node->inputs[0]; - if (input_node->op == "Shape") + if(input_node->op == "Shape") { /* here we go */ DisconnectNode(cur_node); @@ -1069,16 +1067,16 @@ int tensorflow_serializer::optimize_graph() ir = tf_graph.seq_nodes.begin(); - while (ir != tf_graph.seq_nodes.end()) + while(ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if (cur_node->op == "Conv2D" || cur_node->op == "DepthwiseConv2dNative") + if(cur_node->op == "Conv2D" || cur_node->op == "DepthwiseConv2dNative") { /* check if input is pad or not */ TFNode* input_node = cur_node->inputs[0]; - if (input_node->op == "Pad") + if(input_node->op == "Pad") { TFNode* padding_args = input_node->inputs[1]; @@ -1094,10 +1092,10 @@ int tensorflow_serializer::optimize_graph() /*remove ArgMax node */ ir = tf_graph.seq_nodes.begin(); - while (ir != tf_graph.seq_nodes.end()) + while(ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if (cur_node->op == "ArgMax") + if(cur_node->op == "ArgMax") { DisconnectNode(cur_node); tf_graph.seq_nodes.erase(ir); @@ -1112,11 +1110,11 @@ int tensorflow_serializer::optimize_graph() ir = tf_graph.seq_nodes.begin(); - while (ir != tf_graph.seq_nodes.end()) + while(ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if (cur_node->op == "Squeeze" && cur_node->outputs.empty()) + if(cur_node->op == "Squeeze" && cur_node->outputs.empty()) { DisconnectNode(cur_node); break; @@ -1128,11 +1126,11 @@ int tensorflow_serializer::optimize_graph() ir = tf_graph.seq_nodes.begin(); - while (ir != tf_graph.seq_nodes.end()) + while(ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if (cur_node->inputs.size() == 0 && cur_node->outputs.size() == 0) + if(cur_node->inputs.size() == 0 && cur_node->outputs.size() == 0) { ir = tf_graph.seq_nodes.erase(ir); delete cur_node; @@ -1144,17 +1142,18 @@ int tensorflow_serializer::optimize_graph() /* remove no input but not placeholder/const nodes */ ir = tf_graph.seq_nodes.begin(); - while (ir != tf_graph.seq_nodes.end()) + while(ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if (cur_node->inputs.size() == 0 && cur_node->op != "Const" && cur_node->op != "Placeholder" && cur_node->op != "FIFOQueueV2") + if(cur_node->inputs.size() == 0 && cur_node->op != "Const" && cur_node->op != "Placeholder" && + cur_node->op != "FIFOQueueV2") { DisconnectNode(cur_node); tf_graph.seq_nodes.erase(ir); delete cur_node; - ir = tf_graph.seq_nodes.begin(); // restart + ir = tf_graph.seq_nodes.begin(); // restart } else ir++; @@ -1163,6 +1162,7 @@ int tensorflow_serializer::optimize_graph() return 0; } + int tensorflow_serializer::FindRNNScope(std::string& rnn_scope) { std::string rnn_node; @@ -1171,19 +1171,19 @@ int tensorflow_serializer::FindRNNScope(std::string& rnn_scope) int rnn_type = -1; - for (unsigned int i = 0; i < tf_graph.seq_nodes.size(); i++) + for(unsigned int i = 0; i < tf_graph.seq_nodes.size(); i++) { TFNode* node = tf_graph.seq_nodes.at(i); std::string& name = node->name; while_pos = name.find("while"); - if (while_pos == std::string::npos) + if(while_pos == std::string::npos) continue; std::string::size_type cell_pos = name.find("lstm_cell", while_pos); - if (cell_pos != std::string::npos) + if(cell_pos != std::string::npos) { rnn_node = node->name; rnn_type = TF_RNN_LSTM; @@ -1192,7 +1192,7 @@ int tensorflow_serializer::FindRNNScope(std::string& rnn_scope) cell_pos = name.find("gru_cell", while_pos); - if (cell_pos != std::string::npos) + if(cell_pos != std::string::npos) { rnn_node = node->name; rnn_type = TF_RNN_GRU; @@ -1201,7 +1201,7 @@ int tensorflow_serializer::FindRNNScope(std::string& rnn_scope) cell_pos = name.find("basic_lstm_cell", while_pos); - if (cell_pos != std::string::npos) + if(cell_pos != std::string::npos) { rnn_node = node->name; rnn_type = TF_RNN_BASIC_LSTM; @@ -1210,7 +1210,7 @@ int tensorflow_serializer::FindRNNScope(std::string& rnn_scope) cell_pos = name.find("basic_rnn_cell", while_pos); - if (cell_pos != std::string::npos) + if(cell_pos != std::string::npos) { rnn_node = node->name; rnn_type = TF_RNN_BASIC_RNN; @@ -1218,7 +1218,7 @@ int tensorflow_serializer::FindRNNScope(std::string& rnn_scope) } } - if (rnn_node.empty()) + if(rnn_node.empty()) return -1; std::string rnn_layer = rnn_node.substr(0, while_pos - 1); @@ -1233,36 +1233,36 @@ void tensorflow_serializer::ParseLSTMGraph(LSTMNode* lstm_node, std::setinputs.size(); i++) + for(unsigned int i = 0; i < lstm_node->inputs.size(); i++) { TFNode* node = lstm_node->inputs[i]; - if (node->op != "Const") + if(node->op != "Const") continue; // node->no_static_node=true; //do not automatically create Static Node - if (node->name.find("lstm_cell/kernel") != std::string::npos) + if(node->name.find("lstm_cell/kernel") != std::string::npos) { lstm_node->kernel = node; } - else if (node->name.find("lstm_cell/bias") != std::string::npos) + else if(node->name.find("lstm_cell/bias") != std::string::npos) { lstm_node->bias = node; } - else if (node->name.find("lstm_cell/w_f_diag") != std::string::npos) + else if(node->name.find("lstm_cell/w_f_diag") != std::string::npos) { lstm_node->w_f_diag = node; } - else if (node->name.find("lstm_cell/w_o_diag") != std::string::npos) + else if(node->name.find("lstm_cell/w_o_diag") != std::string::npos) { lstm_node->w_o_diag = node; } - else if (node->name.find("lstm_cell/w_i_diag") != std::string::npos) + else if(node->name.find("lstm_cell/w_i_diag") != std::string::npos) { lstm_node->w_i_diag = node; } - else if (node->name.find("lstm_cell/projection/kernel") != std::string::npos) + else if(node->name.find("lstm_cell/projection/kernel") != std::string::npos) { lstm_node->projection = node; } @@ -1271,7 +1271,7 @@ void tensorflow_serializer::ParseLSTMGraph(LSTMNode* lstm_node, std::setname.size(); @@ -1279,11 +1279,11 @@ void tensorflow_serializer::ParseLSTMGraph(LSTMNode* lstm_node, std::setname.find(zero_name, name_len - zero_name.size()) != std::string::npos) + if(node->name.find(zero_name, name_len - zero_name.size()) != std::string::npos) lstm_node->init_c = node; - else if (node->name.find(zero1_name, name_len - zero1_name.size()) != std::string::npos) + else if(node->name.find(zero1_name, name_len - zero1_name.size()) != std::string::npos) lstm_node->init_h = node; - else if (node->name.find(forget_name, name_len - forget_name.size()) != std::string::npos) + else if(node->name.find(forget_name, name_len - forget_name.size()) != std::string::npos) lstm_node->forget_bias = node; rnn_ir++; @@ -1293,28 +1293,28 @@ void ParseGRUGraph(TFGraph& tf_graph, GRUNode* gru_node, std::set& rnn_ { /* parse input node */ - for (unsigned int i = 0; i < gru_node->inputs.size(); i++) + for(unsigned int i = 0; i < gru_node->inputs.size(); i++) { TFNode* node = gru_node->inputs[i]; - if (node->op != "Const") + if(node->op != "Const") continue; // node->no_static_node=true; //do not automatically create Static Node - if (node->name.find("gru_cell/gates/kernel") != std::string::npos) + if(node->name.find("gru_cell/gates/kernel") != std::string::npos) { gru_node->gate_kernel = node; } - else if (node->name.find("gru_cell/gates/bias") != std::string::npos) + else if(node->name.find("gru_cell/gates/bias") != std::string::npos) { gru_node->gate_bias = node; } - else if (node->name.find("gru_cell/candidate/kernel") != std::string::npos) + else if(node->name.find("gru_cell/candidate/kernel") != std::string::npos) { gru_node->candidate_kernel = node; } - else if (node->name.find("gru_cell/candidate/bias") != std::string::npos) + else if(node->name.find("gru_cell/candidate/bias") != std::string::npos) { gru_node->candidate_bias = node; } @@ -1323,13 +1323,13 @@ void ParseGRUGraph(TFGraph& tf_graph, GRUNode* gru_node, std::set& rnn_ auto rnn_ir = rnn_graph.begin(); auto rnn_ir_end = rnn_graph.end(); - while (rnn_ir != rnn_ir_end) + while(rnn_ir != rnn_ir_end) { TFNode* node = *rnn_ir; int name_len = node->name.size(); std::string zero_name = "GRUCellZeroState/zeros"; - if (node->name.find(zero_name, name_len - zero_name.size()) != std::string::npos) + if(node->name.find(zero_name, name_len - zero_name.size()) != std::string::npos) gru_node->init_h = node; rnn_ir++; @@ -1339,20 +1339,20 @@ void ParseRNNGraph(TFGraph& tf_graph, RNNNode* rnn_node, std::set& rnn_ { /* parse input node */ - for (unsigned int i = 0; i < rnn_node->inputs.size(); i++) + for(unsigned int i = 0; i < rnn_node->inputs.size(); i++) { TFNode* node = rnn_node->inputs[i]; - if (node->op != "Const") + if(node->op != "Const") continue; // node->no_static_node=true; //do not automatically create Static Node - if (node->name.find("basic_rnn_cell/kernel") != std::string::npos) + if(node->name.find("basic_rnn_cell/kernel") != std::string::npos) { rnn_node->kernel = node; } - else if (node->name.find("basic_rnn_cell/bias") != std::string::npos) + else if(node->name.find("basic_rnn_cell/bias") != std::string::npos) { rnn_node->bias = node; } @@ -1361,13 +1361,13 @@ void ParseRNNGraph(TFGraph& tf_graph, RNNNode* rnn_node, std::set& rnn_ auto rnn_ir = rnn_graph.begin(); auto rnn_ir_end = rnn_graph.end(); - while (rnn_ir != rnn_ir_end) + while(rnn_ir != rnn_ir_end) { TFNode* node = *rnn_ir; int name_len = node->name.size(); std::string zero_name = "BasicRNNCellZeroState/zeros"; - if (node->name.find(zero_name, name_len - zero_name.size()) != std::string::npos) + if(node->name.find(zero_name, name_len - zero_name.size()) != std::string::npos) rnn_node->init_h = node; rnn_ir++; @@ -1377,7 +1377,7 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) { // collect attributes according to rnn_type - if (rnn_type == TF_RNN_LSTM) + if(rnn_type == TF_RNN_LSTM) { LSTMNode* lstm_node = new LSTMNode(); @@ -1392,11 +1392,11 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) auto ir = tf_graph.seq_nodes.begin(); std::string::size_type prefix_len = rnn_scope.size(); - while (ir != tf_graph.seq_nodes.end()) + while(ir != tf_graph.seq_nodes.end()) { TFNode* node = *ir; - if (node->name.find(rnn_scope.c_str(), 0, prefix_len) == std::string::npos) + if(node->name.find(rnn_scope.c_str(), 0, prefix_len) == std::string::npos) { ir++; continue; @@ -1411,23 +1411,23 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) auto rnn_ir = rnn_graph.begin(); auto rnn_end = rnn_graph.end(); - while (rnn_ir != rnn_end) + while(rnn_ir != rnn_end) { TFNode* node = *rnn_ir; - for (unsigned int i = 0; i < node->inputs.size(); i++) + for(unsigned int i = 0; i < node->inputs.size(); i++) { TFNode* input = node->inputs[i]; - if (!rnn_graph.count(input)) + if(!rnn_graph.count(input)) rnn_inputs.insert(input); } - for (unsigned int i = 0; i < node->outputs.size(); i++) + for(unsigned int i = 0; i < node->outputs.size(); i++) { TFNode* output = node->outputs[i]; - if (!rnn_graph.count(output)) + if(!rnn_graph.count(output)) rnn_outputs.insert(output); } @@ -1437,11 +1437,11 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) // insert lstm node auto seq_ir = tf_graph.seq_nodes.begin(); - while (seq_ir != tf_graph.seq_nodes.end()) + while(seq_ir != tf_graph.seq_nodes.end()) { TFNode* node = *seq_ir; - if (rnn_inputs.count(node)) + if(rnn_inputs.count(node)) { tf_graph.seq_nodes.insert(seq_ir, lstm_node); break; @@ -1454,21 +1454,21 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) auto set_ir = rnn_inputs.begin(); auto set_ir_end = rnn_inputs.end(); - while (set_ir != set_ir_end) + while(set_ir != set_ir_end) { TFNode* input_node = *set_ir; - for (unsigned int j = 0; j < input_node->outputs.size(); j++) + for(unsigned int j = 0; j < input_node->outputs.size(); j++) { TFNode* child_node = input_node->outputs[j]; - if (rnn_graph.count(child_node)) + if(rnn_graph.count(child_node)) input_node->outputs[j] = lstm_node; } lstm_node->inputs.push_back(input_node); - if (input_node->op == "Identity") + if(input_node->op == "Identity") { TFNode* parent_node = input_node->inputs[0]; @@ -1481,15 +1481,15 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) set_ir = rnn_outputs.begin(); set_ir_end = rnn_outputs.end(); - while (set_ir != set_ir_end) + while(set_ir != set_ir_end) { TFNode* output_node = *set_ir; - for (unsigned int j = 0; j < output_node->inputs.size(); j++) + for(unsigned int j = 0; j < output_node->inputs.size(); j++) { TFNode* parent_node = output_node->inputs[j]; - if (rnn_graph.count(parent_node)) + if(rnn_graph.count(parent_node)) output_node->inputs[j] = lstm_node; } @@ -1507,7 +1507,7 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) ParseLSTMGraph(lstm_node, rnn_graph); } - if (rnn_type == TF_RNN_BASIC_RNN) + if(rnn_type == TF_RNN_BASIC_RNN) { RNNNode* rnn_node = new RNNNode(); @@ -1523,11 +1523,11 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) auto ir = tf_graph.seq_nodes.begin(); std::string::size_type prefix_len = rnn_scope.size(); - while (ir != tf_graph.seq_nodes.end()) + while(ir != tf_graph.seq_nodes.end()) { TFNode* node = *ir; - if (node->name.find(rnn_scope.c_str(), 0, prefix_len) == std::string::npos) + if(node->name.find(rnn_scope.c_str(), 0, prefix_len) == std::string::npos) { ir++; continue; @@ -1542,23 +1542,23 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) auto rnn_ir = rnn_graph.begin(); auto rnn_end = rnn_graph.end(); - while (rnn_ir != rnn_end) + while(rnn_ir != rnn_end) { TFNode* node = *rnn_ir; - for (unsigned int i = 0; i < node->inputs.size(); i++) + for(unsigned int i = 0; i < node->inputs.size(); i++) { TFNode* input = node->inputs[i]; - if (!rnn_graph.count(input)) + if(!rnn_graph.count(input)) rnn_inputs.insert(input); } - for (unsigned int i = 0; i < node->outputs.size(); i++) + for(unsigned int i = 0; i < node->outputs.size(); i++) { TFNode* output = node->outputs[i]; - if (!rnn_graph.count(output)) + if(!rnn_graph.count(output)) rnn_outputs.insert(output); } @@ -1568,11 +1568,11 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) // insert rnn node auto seq_ir = tf_graph.seq_nodes.begin(); - while (seq_ir != tf_graph.seq_nodes.end()) + while(seq_ir != tf_graph.seq_nodes.end()) { TFNode* node = *seq_ir; - if (rnn_inputs.count(node)) + if(rnn_inputs.count(node)) { tf_graph.seq_nodes.insert(seq_ir, rnn_node); break; @@ -1585,21 +1585,21 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) auto set_ir = rnn_inputs.begin(); auto set_ir_end = rnn_inputs.end(); - while (set_ir != set_ir_end) + while(set_ir != set_ir_end) { TFNode* input_node = *set_ir; - for (unsigned int j = 0; j < input_node->outputs.size(); j++) + for(unsigned int j = 0; j < input_node->outputs.size(); j++) { TFNode* child_node = input_node->outputs[j]; - if (rnn_graph.count(child_node)) + if(rnn_graph.count(child_node)) input_node->outputs[j] = rnn_node; } rnn_node->inputs.push_back(input_node); - if (input_node->op == "Identity") + if(input_node->op == "Identity") { TFNode* parent_node = input_node->inputs[0]; @@ -1612,15 +1612,15 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) set_ir = rnn_outputs.begin(); set_ir_end = rnn_outputs.end(); - while (set_ir != set_ir_end) + while(set_ir != set_ir_end) { TFNode* output_node = *set_ir; - for (unsigned int j = 0; j < output_node->inputs.size(); j++) + for(unsigned int j = 0; j < output_node->inputs.size(); j++) { TFNode* parent_node = output_node->inputs[j]; - if (rnn_graph.count(parent_node)) + if(rnn_graph.count(parent_node)) output_node->inputs[j] = rnn_node; } @@ -1637,7 +1637,7 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) ParseRNNGraph(tf_graph, rnn_node, rnn_graph); } - if (rnn_type == TF_RNN_GRU) + if(rnn_type == TF_RNN_GRU) { GRUNode* gru_node = new GRUNode(); @@ -1653,11 +1653,11 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) auto ir = tf_graph.seq_nodes.begin(); std::string::size_type prefix_len = rnn_scope.size(); - while (ir != tf_graph.seq_nodes.end()) + while(ir != tf_graph.seq_nodes.end()) { TFNode* node = *ir; - if (node->name.find(rnn_scope.c_str(), 0, prefix_len) == std::string::npos) + if(node->name.find(rnn_scope.c_str(), 0, prefix_len) == std::string::npos) { ir++; continue; @@ -1672,23 +1672,23 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) auto rnn_ir = rnn_graph.begin(); auto rnn_end = rnn_graph.end(); - while (rnn_ir != rnn_end) + while(rnn_ir != rnn_end) { TFNode* node = *rnn_ir; - for (unsigned int i = 0; i < node->inputs.size(); i++) + for(unsigned int i = 0; i < node->inputs.size(); i++) { TFNode* input = node->inputs[i]; - if (!rnn_graph.count(input)) + if(!rnn_graph.count(input)) rnn_inputs.insert(input); } - for (unsigned int i = 0; i < node->outputs.size(); i++) + for(unsigned int i = 0; i < node->outputs.size(); i++) { TFNode* output = node->outputs[i]; - if (!rnn_graph.count(output)) + if(!rnn_graph.count(output)) rnn_outputs.insert(output); } @@ -1698,11 +1698,11 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) // insert rnn node auto seq_ir = tf_graph.seq_nodes.begin(); - while (seq_ir != tf_graph.seq_nodes.end()) + while(seq_ir != tf_graph.seq_nodes.end()) { TFNode* node = *seq_ir; - if (rnn_inputs.count(node)) + if(rnn_inputs.count(node)) { tf_graph.seq_nodes.insert(seq_ir, gru_node); break; @@ -1715,21 +1715,21 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) auto set_ir = rnn_inputs.begin(); auto set_ir_end = rnn_inputs.end(); - while (set_ir != set_ir_end) + while(set_ir != set_ir_end) { TFNode* input_node = *set_ir; - for (unsigned int j = 0; j < input_node->outputs.size(); j++) + for(unsigned int j = 0; j < input_node->outputs.size(); j++) { TFNode* child_node = input_node->outputs[j]; - if (rnn_graph.count(child_node)) + if(rnn_graph.count(child_node)) input_node->outputs[j] = gru_node; } gru_node->inputs.push_back(input_node); - if (input_node->op == "Identity") + if(input_node->op == "Identity") { TFNode* parent_node = input_node->inputs[0]; @@ -1742,15 +1742,15 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) set_ir = rnn_outputs.begin(); set_ir_end = rnn_outputs.end(); - while (set_ir != set_ir_end) + while(set_ir != set_ir_end) { TFNode* output_node = *set_ir; - for (unsigned int j = 0; j < output_node->inputs.size(); j++) + for(unsigned int j = 0; j < output_node->inputs.size(); j++) { TFNode* parent_node = output_node->inputs[j]; - if (rnn_graph.count(parent_node)) + if(rnn_graph.count(parent_node)) output_node->inputs[j] = gru_node; } @@ -1771,11 +1771,11 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) // cleanup zero in/zero out node auto seq_ir = tf_graph.seq_nodes.begin(); - while (seq_ir != tf_graph.seq_nodes.end()) + while(seq_ir != tf_graph.seq_nodes.end()) { TFNode* node = *seq_ir; - if (node->inputs.size() == 0 && node->outputs.size() == 0) + if(node->inputs.size() == 0 && node->outputs.size() == 0) { delete node; seq_ir = tf_graph.seq_nodes.erase(seq_ir); @@ -1788,13 +1788,13 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) } int tensorflow_serializer::optimize_rnn() { - while (1) + while(1) { std::string rnn_scope; int rnn_type = FindRNNScope(rnn_scope); - if (rnn_scope.empty()) + if(rnn_scope.empty()) break; StripRNNScope(rnn_scope, rnn_type); @@ -1803,6 +1803,7 @@ int tensorflow_serializer::optimize_rnn() return true; } + int tensorflow_serializer::generate_graph(ir_graph_t* graph) { int node_number = tf_graph.seq_nodes.size(); @@ -1810,44 +1811,45 @@ int tensorflow_serializer::generate_graph(ir_graph_t* graph) bool debug_graph = false; const char* debug_env = std::getenv("DEBUG_TF"); - if ((debug_env) && (debug_env[0] == '1')) + if((debug_env) && (debug_env[0] == '1')) { debug_graph = true; } // first: create all tensor node - for (i = 0; i < node_number; i++) + for(i = 0; i < node_number; i++) { TFNode* tf_node = tf_graph.seq_nodes[i]; - if (debug_graph) + if(debug_graph) { std::cout << i << "\t" << tf_node->op << "\t" << tf_node->name << "\n"; } - if (tf_node->no_static_node) + if(tf_node->no_static_node) continue; - if (tf_node->op == "Placeholder") + if(tf_node->op == "Placeholder") continue; - if (tf_node->op == "Const") + + if(tf_node->op == "Const") { load_const_tensor(tf_node, graph); continue; } - } + } - for (int i = 0; i < (int)tf_graph.seq_nodes.size(); i++) + for(int i = 0; i < (int)tf_graph.seq_nodes.size(); i++) { TFNode* tf_node = tf_graph.seq_nodes[i]; - if (tf_node->op == "Placeholder" || tf_node->op == "Const") + if(tf_node->op == "Placeholder" || tf_node->op == "Const") continue; ir_node_t* ir_node = nullptr; int node_idx = get_ir_node_index_from_name(graph, tf_node->name.c_str()); - if (node_idx < 0) + if(node_idx < 0) { ir_node = create_ir_node(graph, tf_node->name.c_str(), op_load_map[tf_node->op].first, OP_VERSION); } @@ -1855,62 +1857,45 @@ int tensorflow_serializer::generate_graph(ir_graph_t* graph) { ir_node = get_ir_graph_node(graph, node_idx); } - for (int in = 0; in < tf_node->inputs.size(); in++) + for(int in = 0; in < tf_node->inputs.size(); in++) { TFNode* node = tf_node->inputs[in]; int tensor_idx = get_ir_tensor_index_from_name(graph, node->name.c_str()); ir_tensor_t* tensor = nullptr; - if (node->name == "Placeholder") + if(node->name == "Placeholder") { continue; } - if (tensor_idx < 0) - tensor = create_ir_tensor(graph, tf_node->name.c_str(), TENGINE_DT_FP32); + if(tensor_idx < 0) + tensor = create_ir_tensor(graph, tf_node->name.c_str(),TENGINE_DT_FP32 ); else tensor = get_ir_graph_tensor(graph, tensor_idx); set_ir_node_input_tensor(ir_node, in, tensor); input_tensors.push_back(node->name.c_str()); } - for (int out = 0; out < tf_node->outputs.size(); out++) + for(int out = 0; out < tf_node->outputs.size(); out++) { TFNode* node = tf_node->outputs[out]; int tensor_idx = get_ir_tensor_index_from_name(graph, node->name.c_str()); ir_tensor_t* tensor = nullptr; - if (tensor_idx < 0) - tensor = create_ir_tensor(graph, tf_node->name.c_str(), TENGINE_DT_FP32); + if(tensor_idx < 0) + tensor = create_ir_tensor(graph, tf_node->name.c_str(),TENGINE_DT_FP32 ); else tensor = get_ir_graph_tensor(graph, tensor_idx); set_ir_node_output_tensor(ir_node, out, tensor); output_tensors.push_back(node->name.c_str()); } - + // printf("node op : %s \n", tf_node->op.c_str()); op_load_t loader = op_load_map[tf_node->op].second; if (loader(tf_node, tf_graph, graph, ir_node) < 0) { fprintf(stderr, "load op %s func failed in node %s .\n", tf_node->op.c_str(), tf_node->name.c_str()); return -1; } - } - - // for(i = 0; i < (int)tf_graph.seq_nodes.size(); i++) - // { - // TFNode* tf_node = tf_graph.seq_nodes[i]; - - // if(tf_node->op == "Placeholder" || tf_node->op == "Const") - // continue; - - // op_load_t loader = op_load_map[tf_node->op].second; - // // printf("%s \n", tf_node->op.c_str()); - // if (loader(tf_node, tf_graph, graph) < 0) - // { - // fprintf(stderr, "load op %s func failed in node %s .\n", tf_node->op.c_str(), tf_node->name.c_str()); - // return -1; - // } - - // } + } - if (i < node_number) + if(i < node_number) return -1; return 0; @@ -1937,11 +1922,11 @@ int tensorflow_serializer::set_graph_output(ir_graph_t* graph) { int tensor_id = get_ir_tensor_index_from_name(graph, graph_outputs[i].c_str()); ir_tensor_t* tensor = nullptr; - if (tensor_id < 0) - tensor = create_ir_tensor(graph, graph_outputs[i].c_str(), TENGINE_DT_FP32); + if(tensor_id < 0) + tensor = create_ir_tensor(graph, graph_outputs[i].c_str(),TENGINE_DT_FP32 ); else tensor = get_ir_graph_tensor(graph, tensor_id); - int node_idx = get_ir_node_index_from_name(graph, graph_outputs[i].c_str()); + int node_idx = get_ir_node_index_from_name(graph,graph_outputs[i].c_str() ); ir_node_t* node = get_ir_graph_node(graph, node_idx); set_ir_node_output_tensor(node, 0, tensor); output_nodes.push_back(node->index); @@ -1979,6 +1964,7 @@ int tensorflow_serializer::load_graph(ir_graph_t* graph) return 0; } + int tensorflow_serializer::load_model(ir_graph_t* graph, std::string model_file) { register_op_load(); @@ -2022,28 +2008,28 @@ int load_pool(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* const tensorflow::NodeDef* node_def = tf_node->pb_defs[0]; tensorflow::AttrValue value; - if (GetAttrValue(node_def, "ksize", value)) + if(GetAttrValue(node_def, "ksize", value)) { param->kernel_h = value.list().i(1); param->kernel_w = value.list().i(2); } - if (GetAttrValue(node_def, "strides", value)) + if(GetAttrValue(node_def, "strides", value)) { param->stride_h = value.list().i(1); param->stride_w = value.list().i(2); } - if (GetAttrValue(node_def, "padding", value)) + if(GetAttrValue(node_def, "padding", value)) { - if (value.s() == "VALID") + if(value.s() == "VALID") { param->pad_h0 = 0; param->pad_h1 = 0; param->pad_w0 = 0; param->pad_w1 = 0; } - else if (value.s() == "SAME") + else if(value.s() == "SAME") { param->pad_h0 = -1; param->pad_h1 = -1; @@ -2052,13 +2038,13 @@ int load_pool(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* } } - if (tf_node->op == "AvgPool") + if(tf_node->op == "AvgPool") { - param->pool_method = 0; + param->pool_method = 1; } - else if (tf_node->op == "MaxPool") + else if(tf_node->op == "MaxPool") { - param->pool_method = 1; + param->pool_method = 0; } return 0; } @@ -2067,7 +2053,7 @@ int load_conv(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* TFNode* input0 = tf_node->inputs[0]; /* input */ TFNode* input1 = tf_node->inputs[1]; /* weight */ TFNode* input2 = nullptr; - if (tf_node->inputs.size() > 2) + if(tf_node->inputs.size() > 2) { input2 = tf_node->inputs[2]; } @@ -2075,21 +2061,21 @@ int load_conv(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* struct conv_param* param = (struct conv_param*)node->op.param_mem; tensorflow::AttrValue value; - if (GetAttrValue(node_def, "dilations", value)) + if(GetAttrValue(node_def, "dilations", value)) { param->dilation_h = value.list().i(1); param->dilation_w = value.list().i(2); } - if (GetAttrValue(node_def, "padding", value)) + if(GetAttrValue(node_def, "padding", value)) { - if (value.s() == "VALID") + if(value.s() == "VALID") { param->pad_h0 = 0; param->pad_h1 = 0; param->pad_w0 = 0; param->pad_w1 = 0; } - else if (value.s() == "SAME") + else if(value.s() == "SAME") { param->pad_h0 = -1; param->pad_h1 = -1; @@ -2098,7 +2084,7 @@ int load_conv(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* } } - if (GetAttrValue(node_def, "strides", value)) + if(GetAttrValue(node_def, "strides", value)) { param->stride_h = value.list().i(1); param->stride_w = value.list().i(2); @@ -2110,18 +2096,18 @@ int load_conv(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* const tensorflow::NodeDef* weight_def = input1->pb_defs[0]; - if (GetAttrValue(weight_def, "value", value)) + if(GetAttrValue(weight_def, "value", value)) { const tensorflow::TensorShapeProto& shape = value.tensor().tensor_shape(); - if (shape.dim_size() == 4) + if(shape.dim_size() == 4) { kernel_h = shape.dim(0).size(); kernel_w = shape.dim(1).size(); in_channel = shape.dim(2).size(); out_channel = shape.dim(3).size(); } - else if (shape.dim_size() == 3) + else if(shape.dim_size() == 3) { kernel_h = 1; kernel_w = shape.dim(0).size(); @@ -2132,46 +2118,36 @@ int load_conv(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* ir_tensor_t* weight_tensor = input1->ir_tensor; int elem_size = out_channel * in_channel * kernel_h * kernel_w; - float* new_weight = (float*)malloc(sizeof(float) * elem_size); + float* new_weight = ( float* )malloc(sizeof(float) * elem_size); float* src = (float*)weight_tensor->data; - weight_tensor->data = sys_malloc(elem_size * sizeof(float)); + weight_tensor->data = sys_malloc(elem_size*sizeof(float)); float* ptr = (float*)weight_tensor->data; - for (int o = 0; o < out_channel; o++) - for (int h = 0; h < kernel_h; h++) - for (int w = 0; w < kernel_w; w++) - for (int i = 0; i < in_channel; i++) + for(int o = 0; o < out_channel; o++) + for(int h = 0; h < kernel_h; h++) + for(int w = 0; w < kernel_w; w++) + for(int i = 0; i < in_channel; i++) { - ptr[o * in_channel * kernel_h * kernel_w + i * kernel_h * kernel_w + h * kernel_w + w] - = src[h * (kernel_w * in_channel * out_channel) + w * (in_channel * out_channel) + i * out_channel + o]; + ptr[o*in_channel*kernel_h*kernel_w + i*kernel_h*kernel_w + h*kernel_w + w] + = src[h * (kernel_w * in_channel * out_channel) + w * (in_channel * out_channel) + i * out_channel + o]; } free(src); weight_tensor->tensor_type = TENSOR_TYPE_CONST; - if (tf_node->op == "DepthwiseConv2dNative") + if(tf_node->op == "DepthwiseConv2dNative") { group = in_channel; out_channel = in_channel * out_channel; in_channel = 1; } - int* dims = (int*)malloc(sizeof(int) * 4); + int* dims = (int*)malloc(sizeof(int)*4); dims[0] = out_channel; dims[1] = in_channel; dims[2] = kernel_h; dims[3] = kernel_w; -#if 0 - dims.push_back(out_channel); - dims.push_back(kernel_h); - dims.push_back(kernel_w); - dims.push_back(in_channel); -// #else - dims.push_back(out_channel); - dims.push_back(in_channel); - dims.push_back(kernel_h); - dims.push_back(kernel_w); -#endif + // SetTensorDim(weight_tensor, dims); set_ir_tensor_shape(weight_tensor, dims, 4); param->kernel_h = kernel_h; @@ -2179,7 +2155,9 @@ int load_conv(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* param->output_channel = out_channel; param->group = group; - if (tf_node->op == "DepthwiseConv2dNative") + auto saved_param = param; + + if(tf_node->op == "DepthwiseConv2dNative") { in_channel = group; out_channel = out_channel / in_channel; @@ -2187,47 +2165,49 @@ int load_conv(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* int pb_def_num = tf_node->pb_defs.size(); - if (pb_def_num > 1) + if(pb_def_num > 1) { // the last one, const tensorflow::NodeDef* node_def = tf_node->pb_defs[pb_def_num - 1]; /* possible pad */ - if (node_def->op() == "Const") + if(node_def->op() == "Const") { tensorflow::AttrValue value; - if (GetAttrValue(node_def, "value", value) && value.has_tensor()) + if(GetAttrValue(node_def, "value", value) && value.has_tensor()) { const tensorflow::TensorProto& tf_tensor = value.tensor(); int dim_size = tf_tensor.tensor_shape().dim_size(); - if (dim_size == 2 && tf_tensor.tensor_shape().dim(0).size() == 4 && tf_tensor.tensor_shape().dim(1).size() == 2) + if(dim_size == 2 && tf_tensor.tensor_shape().dim(0).size() == 4 && + tf_tensor.tensor_shape().dim(1).size() == 2) { std::vector shape_data(8); - if (tf_tensor.tensor_content().size()) + if(tf_tensor.tensor_content().size()) { - // int* dst = shape_data.data(); + int* ptr = shape_data.data(); memcpy(ptr, tf_tensor.tensor_content().c_str(), tf_tensor.tensor_content().size()); } else { int data_num = tf_tensor.int_val_size(); - for (int i = 0; i < data_num; i++) + for(int i = 0; i < data_num; i++) { shape_data[i] = tf_tensor.int_val(i); } } /* h pad */ - param->pad_h0 = shape_data[2]; - param->pad_h1 = shape_data[3]; + saved_param->pad_h0 = shape_data[2]; + saved_param->pad_h1 = shape_data[3]; /* w pad */ - param->pad_w0 = shape_data[4]; - param->pad_w1 = shape_data[5]; + saved_param->pad_w0 = shape_data[4]; + saved_param->pad_w1 = shape_data[5]; + // printf("%d %d %d %d \n",) } } } @@ -2240,7 +2220,7 @@ int load_batchnorm(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_nod const tensorflow::NodeDef* node_def = tf_node->pb_defs[0]; tensorflow::AttrValue value; - if (GetAttrValue(node_def, "epsilon", value)) + if(GetAttrValue(node_def, "epsilon", value)) { param->eps = value.f(); } @@ -2253,6 +2233,18 @@ int load_relu6(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* } int load_softmax(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* node) { + struct softmax_param* param = (struct softmax_param*)node->op.param_mem; + const tensorflow::NodeDef* node_def = tf_node->pb_defs[0]; + tensorflow::AttrValue value; + if(GetAttrValue(node_def, "value", value)) + { + const tensorflow::TensorProto& tf_tensor = value.tensor(); + int axis = tf_tensor.int_val(0); + param->axis = axis; + } + else + param->axis = 1; + return 0; } int load_relu(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* node) @@ -2262,15 +2254,165 @@ int load_relu(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* param->negative_slope = 0.f; return 0; } +static EltType MapEltwise(TFNode* tf_node, const std::string& elt_op) +{ + if(elt_op == "Add" || elt_op == "AddN") + return ELT_SUM; + else if(elt_op == "Mul") + return ELT_PROD; + else if(elt_op == "Sub") + return ELT_SUB; + else if(elt_op == "Rsqrt") + return ELT_RSQRT; + else if(elt_op == "Minimum") + return ELT_MIN_SCALAR; + else if(elt_op == "Exp") + return ELT_EXP; + else if(elt_op == "Log") + return ELT_LOG; + else if(elt_op == "Pow") + return ELT_POW; + else if(elt_op == "RealDiv") + return ELT_DIV; + else if(elt_op == "Sqrt") + return ELT_SQRT; + else if(elt_op == "Floor") + return ELT_FLOOR; + else + return ELT_LAST; +} +int load_eltwise(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* node) +{ + if(tf_node->op == "Add" || tf_node->op == "Mul" || tf_node->op == "Sub" || tf_node->op == "Minimum" || + tf_node->op == "AddN" || tf_node->op == "Pow" || tf_node->op == "RealDiv") + { + if(tf_node->inputs.size() != 2) + return false; + } + else if(tf_node->op == "Rsqrt" || tf_node->op == "Exp" || tf_node->op == "Log" || tf_node->op == "Sqrt" || + tf_node->op == "Floor") + { + if(tf_node->inputs.size() != 1) + return false; + } + else + { + TLOG_ERR("Unsupported op: %s \n", tf_node->op.c_str()); + return false; + } + struct eltwise_param* param = (struct eltwise_param*)node->op.param_mem; + param->type = MapEltwise(tf_node, tf_node->op); + param->caffe_flavor = 1; + return 0; +} +static void* LoadConstParam(TFNode* tf_node) +{ + tensorflow::AttrValue value; + + const tensorflow::NodeDef* node_def = tf_node->pb_defs[0]; + + if(GetAttrValue(node_def, "value", value)) + { + const tensorflow::TensorProto& tf_tensor = value.tensor(); + void* mem_ptr = nullptr; + int* dims; + std::string layout; + int dim_num = GetTensorContentAndDim(tf_tensor, &dims, &mem_ptr, layout); + return mem_ptr; + } + + return nullptr; +} +int load_reduction(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* node) +{ + TFNode* input1 = tf_node->inputs[1]; + struct reduction_param* param = (struct reduction_param*)node->op.param_mem; + const tensorflow::NodeDef* node_def = tf_node->pb_defs[0]; + tensorflow::AttrValue value; + GetAttrValue(node_def, "keep_dims", value); + param->keepdim = value.b(); + if(tf_node->op == "Sum") + { + param->type = 0; + } + else if(tf_node->op == "Mean") + { + param->type = 1; + } + else if(tf_node->op == "Asum") + { + param->type = 2; + } + else if(tf_node->op == "Sqsum") + { + param->type = 3; + } + else if(tf_node->op == "Max") + { + param->type = 4; + } + else if(tf_node->op == "Min") + { + param->type = 5; + } + else if(tf_node->op == "Prod") + { + param->type = 6; + } + else if(tf_node->op == "L2") + { + param->type = 7; + } + else if(tf_node->op == "Logsum") + { + param->type = 8; + } + else if(tf_node->op == "Logsumexp") + { + param->type = 9; + } + int* data = (int*)LoadConstParam(input1); + return 0; +} +int load_pad(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* node) +{ + struct pad_param* param = (struct pad_param*)node->op.param_mem; + + TFNode* input = tf_node->inputs[1]; + int* paddings = ( int* )LoadConstParam(input); + param->mode = 0; + param->pad_0_h = paddings[0]; + param->pad_0_w = paddings[1]; + param->pad_1_h = paddings[2]; + param->pad_1_w = paddings[3]; + param->pad_2_h = paddings[4]; + param->pad_2_w = paddings[5]; + param->pad_3_h = paddings[6]; + param->pad_3_w = paddings[7]; + return 0; +} void tensorflow_serializer::register_op_load() { - op_load_map["AvgPool"] = std::pair(OP_POOL, load_pool); - op_load_map["MaxPool"] = std::pair(OP_POOL, load_pool); - op_load_map["Conv2D"] = std::pair(OP_CONV, load_conv); - op_load_map["DepthwiseConv2dNative"] = std::pair(OP_CONV, load_conv); - op_load_map["FusedBatchNorm"] = std::pair(OP_BATCHNORM, load_batchnorm); - op_load_map["Relu6"] = std::pair(OP_RELU6, load_relu6); - op_load_map["Relu"] = std::pair(OP_RELU6, load_relu); - op_load_map["Softmax"] = std::pair(OP_SOFTMAX, load_softmax); + op_load_map["AvgPool"] = std::pair(OP_POOL, load_pool); + op_load_map["MaxPool"] = std::pair(OP_POOL, load_pool); + op_load_map["Conv2D"] = std::pair(OP_CONV, load_conv); + op_load_map["DepthwiseConv2dNative"] = std::pair(OP_CONV, load_conv); + op_load_map["FusedBatchNorm"] = std::pair(OP_BATCHNORM, load_batchnorm); + op_load_map["Relu6"] = std::pair(OP_RELU6, load_relu6); + op_load_map["Relu"] = std::pair(OP_RELU, load_relu); + op_load_map["Softmax"] = std::pair(OP_SOFTMAX, load_softmax); + op_load_map["Add"] = std::pair(OP_ELTWISE, load_eltwise); + op_load_map["Sub"] = std::pair(OP_ELTWISE, load_eltwise); + op_load_map["Mul"] = std::pair(OP_ELTWISE, load_eltwise); + op_load_map["Minimum"] = std::pair(OP_ELTWISE, load_eltwise); + op_load_map["Rsqrt"] = std::pair(OP_ELTWISE, load_eltwise); + op_load_map["Exp"] = std::pair(OP_ELTWISE, load_eltwise); + op_load_map["Log"] = std::pair(OP_ELTWISE, load_eltwise); + op_load_map["Pow"] = std::pair(OP_ELTWISE, load_eltwise); + op_load_map["RealDiv"] = std::pair(OP_ELTWISE, load_eltwise); + op_load_map["Sqrt"] = std::pair(OP_ELTWISE, load_eltwise); + op_load_map["AddN"] = std::pair(OP_ELTWISE, load_eltwise); + op_load_map["Mean"] = std::pair(OP_REDUCTION, load_reduction); + op_load_map["Pad"] = std::pair(OP_PAD, load_pad); } \ No newline at end of file From c18f8151b2a5905d02d8cec70d0309d2879ff8fe Mon Sep 17 00:00:00 2001 From: bzhang Date: Fri, 20 Aug 2021 15:13:59 +0800 Subject: [PATCH 5/8] suppoer tensorflow mobilenet --- tools/convert_tool/tensorflow/tf2tengine.hpp | 29 ++++++++++---------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/tools/convert_tool/tensorflow/tf2tengine.hpp b/tools/convert_tool/tensorflow/tf2tengine.hpp index 00199738e..00505fb74 100644 --- a/tools/convert_tool/tensorflow/tf2tengine.hpp +++ b/tools/convert_tool/tensorflow/tf2tengine.hpp @@ -55,10 +55,12 @@ extern "C" { #include "save_graph/op_include.h" } -#define TF_RNN_LSTM 0 -#define TF_RNN_GRU 1 + +#define TF_RNN_LSTM 0 +#define TF_RNN_GRU 1 #define TF_RNN_BASIC_LSTM 2 -#define TF_RNN_BASIC_RNN 3 +#define TF_RNN_BASIC_RNN 3 + struct TFNode { @@ -78,9 +80,7 @@ struct TFNode no_static_node = false; } - virtual ~TFNode() - { - } + virtual ~TFNode() {} }; struct LSTMNode : public TFNode @@ -120,9 +120,9 @@ struct LSTMNode : public TFNode auto rnn_ir = rnn_graph.begin(); auto rnn_end = rnn_graph.end(); - while (rnn_ir != rnn_end) + while(rnn_ir != rnn_end) { - delete (*rnn_ir); + delete(*rnn_ir); rnn_ir++; } } @@ -153,9 +153,9 @@ struct RNNNode : public TFNode auto rnn_ir = rnn_graph.begin(); auto rnn_end = rnn_graph.end(); - while (rnn_ir != rnn_end) + while(rnn_ir != rnn_end) { - delete (*rnn_ir); + delete(*rnn_ir); rnn_ir++; } } @@ -195,9 +195,9 @@ struct GRUNode : public TFNode auto rnn_ir = rnn_graph.begin(); auto rnn_end = rnn_graph.end(); - while (rnn_ir != rnn_end) + while(rnn_ir != rnn_end) { - delete (*rnn_ir); + delete(*rnn_ir); rnn_ir++; } } @@ -209,11 +209,12 @@ struct TFGraph ~TFGraph() { - for (auto node : seq_nodes) + for(auto node : seq_nodes) delete node; } }; + class tensorflow_serializer { public: @@ -238,7 +239,7 @@ class tensorflow_serializer int FindRNNScope(std::string& rnn_scope); void ParseLSTMGraph(LSTMNode* lstm_node, std::set& rnn_graph); void StripRNNScope(std::string& rnn_scope, int rnn_type); - void MergeReluMinimum(); + void MergeReluMinimum(); int MergeChildNode(TFNode* base_node, TFNode* child_node); int MergeParentNode(TFNode* base_node, TFNode* child_node); int BNRecursiveInputMerge(TFNode* node); From 8ca444d66e0fb5a7c8e2c84eaccb12655949c144 Mon Sep 17 00:00:00 2001 From: bzhang5 Date: Fri, 20 Aug 2021 07:14:25 +0000 Subject: [PATCH 6/8] apply code-format changes --- tools/convert_tool/tensorflow/tf2tengine.cpp | 754 +++++++++---------- 1 file changed, 372 insertions(+), 382 deletions(-) diff --git a/tools/convert_tool/tensorflow/tf2tengine.cpp b/tools/convert_tool/tensorflow/tf2tengine.cpp index 4641665fa..db593fc10 100644 --- a/tools/convert_tool/tensorflow/tf2tengine.cpp +++ b/tools/convert_tool/tensorflow/tf2tengine.cpp @@ -53,7 +53,7 @@ static bool GetAttrValue(const tensorflow::NodeDef* node, const char* key, tenso const google::protobuf::Map& attr = node->attr(); const google::protobuf::Map::const_iterator it = attr.find(key); - if(it != attr.end()) + if (it != attr.end()) { value = it->second; return true; @@ -63,15 +63,15 @@ static bool GetAttrValue(const tensorflow::NodeDef* node, const char* key, tenso } int GetTensorContentAndDim(const tensorflow::TensorProto& tf_tensor, int** dims, void** mem_ptr, - std::string& layout) + std::string& layout) { const tensorflow::TensorShapeProto& shape = tf_tensor.tensor_shape(); int elem_num = 1; int dim_num = shape.dim_size(); - int* dim_tmp = (int*)malloc(sizeof(int)*dim_num); - for(int i = 0; i < dim_num; i++) + int* dim_tmp = (int*)malloc(sizeof(int) * dim_num); + for (int i = 0; i < dim_num; i++) { elem_num *= shape.dim(i).size(); dim_tmp[i] = shape.dim(i).size(); @@ -79,22 +79,22 @@ int GetTensorContentAndDim(const tensorflow::TensorProto& tf_tensor, int** dims, void* mem_buf = nullptr; - if(tf_tensor.tensor_content().size()) + if (tf_tensor.tensor_content().size()) { int content_size = tf_tensor.tensor_content().size(); mem_buf = malloc(content_size + 128); - void* src = ( void* )tf_tensor.tensor_content().c_str(); + void* src = (void*)tf_tensor.tensor_content().c_str(); memcpy(mem_buf, src, content_size); } - else if(tf_tensor.dtype() == tensorflow::DataType::DT_FLOAT) + else if (tf_tensor.dtype() == tensorflow::DataType::DT_FLOAT) { // in packed format int data_num = tf_tensor.float_val_size(); mem_buf = malloc(elem_num * sizeof(float)); - float* mem = ( float* )mem_buf; - if(data_num >= elem_num) + float* mem = (float*)mem_buf; + if (data_num >= elem_num) { - for(int i = 0; i < elem_num; i++) + for (int i = 0; i < elem_num; i++) { mem[i] = tf_tensor.float_val(i); } @@ -102,28 +102,28 @@ int GetTensorContentAndDim(const tensorflow::TensorProto& tf_tensor, int** dims, else { // data_num < elem_num - for(int i = 0; i < data_num; i++) + for (int i = 0; i < data_num; i++) { mem[i] = tf_tensor.float_val(i); } - for(int i = data_num; i < elem_num; i++) + for (int i = data_num; i < elem_num; i++) { mem[i] = mem[data_num - 1]; } } } - else if(tf_tensor.dtype() == tensorflow::DataType::DT_INT32) + else if (tf_tensor.dtype() == tensorflow::DataType::DT_INT32) { int data_num = tf_tensor.int_val_size(); mem_buf = malloc(elem_num * sizeof(int)); - int* mem = ( int* )mem_buf; + int* mem = (int*)mem_buf; - if(data_num >= elem_num) + if (data_num >= elem_num) { - for(int i = 0; i < elem_num; i++) + for (int i = 0; i < elem_num; i++) { mem[i] = tf_tensor.int_val(i); } @@ -131,12 +131,12 @@ int GetTensorContentAndDim(const tensorflow::TensorProto& tf_tensor, int** dims, else { // data_num < elem_num - for(int i = 0; i < data_num; i++) + for (int i = 0; i < data_num; i++) { mem[i] = tf_tensor.int_val(i); } - for(int i = data_num; i < elem_num; i++) + for (int i = data_num; i < elem_num; i++) { mem[i] = mem[data_num - 1]; } @@ -145,22 +145,22 @@ int GetTensorContentAndDim(const tensorflow::TensorProto& tf_tensor, int** dims, *mem_ptr = mem_buf; *dims = dim_tmp; - switch(dim_num) - { - case 0: - layout = "W"; - break; - case 1: - layout = "W"; - break; - case 2: - layout = "HW"; - break; - case 4: - layout = "NCHW"; - break; - default: - break; + switch (dim_num) + { + case 0: + layout = "W"; + break; + case 1: + layout = "W"; + break; + case 2: + layout = "HW"; + break; + case 4: + layout = "NCHW"; + break; + default: + break; } return dim_num; } @@ -168,7 +168,7 @@ int tensorflow_serializer::load_binary_file(std::string model_file) { std::ifstream is(model_file.c_str(), std::ios::in | std::ios::binary); - if(!is.is_open()) + if (!is.is_open()) { TLOG_ERR("cannot open file: %s \n", model_file.c_str()); return false; @@ -186,9 +186,9 @@ int tensorflow_serializer::load_binary_file(std::string model_file) is.close(); - if(!ret) + if (!ret) { - TLOG_ERR( "parse file: %s failed\n",model_file.c_str()); + TLOG_ERR("parse file: %s failed\n", model_file.c_str()); return -1; } return ret; @@ -196,27 +196,27 @@ int tensorflow_serializer::load_binary_file(std::string model_file) int load_const_tensor(TFNode* tf_node, ir_graph_t* graph) { ir_node_t* node = create_ir_node(graph, tf_node->name.c_str(), OP_CONST, OP_VERSION); - ir_tensor_t* tensor = create_ir_tensor(graph, tf_node->name.c_str(),TENGINE_DT_FP32); + ir_tensor_t* tensor = create_ir_tensor(graph, tf_node->name.c_str(), TENGINE_DT_FP32); tensorflow::AttrValue value; const tensorflow::NodeDef* node_def = tf_node->pb_defs[0]; - if(GetAttrValue(node_def, "value", value)) + if (GetAttrValue(node_def, "value", value)) { const tensorflow::TensorProto& tf_tensor = value.tensor(); void* mem_ptr; - int* dims ; + int* dims; std::string layout; int dim_num = GetTensorContentAndDim(tf_tensor, &dims, &mem_ptr, layout); set_ir_tensor_shape(tensor, dims, dim_num); int mem_size = 1; - for(int i = 0; i < dim_num; i++) + for (int i = 0; i < dim_num; i++) mem_size *= dims[i]; - tensor->data = (float*)malloc(sizeof(float)*mem_size); + tensor->data = (float*)malloc(sizeof(float) * mem_size); tensor->tensor_type = TENSOR_TYPE_CONST; float* tmp = (float*)mem_ptr; float* tr_tmp = (float*)tensor->data; - for(int i = 0; i < mem_size; i++) + for (int i = 0; i < mem_size; i++) { tr_tmp[i] = tmp[i]; } @@ -230,25 +230,25 @@ int tensorflow_serializer::set_graph_input(ir_graph_t* graph) { int node_num = tf_graph.seq_nodes.size(); std::vector input_nodes; - for(int i = 0; i < node_num; i++) + for (int i = 0; i < node_num; i++) { - TFNode* tf_node =tf_graph.seq_nodes[i]; - if(tf_node->op == "Placeholder") + TFNode* tf_node = tf_graph.seq_nodes[i]; + if (tf_node->op == "Placeholder") { ir_tensor_t* ir_tensor = create_ir_tensor(graph, tf_node->name.c_str(), TENGINE_DT_FP32); tensorflow::AttrValue shape; int pb_defs_cnt = tf_node->pb_defs.size(); int* dims; - if(pb_defs_cnt == 1) + if (pb_defs_cnt == 1) { - if(GetAttrValue(tf_node->pb_defs[0], "shape", shape)) + if (GetAttrValue(tf_node->pb_defs[0], "shape", shape)) { int dim_size = shape.shape().dim_size(); - + dims = (int*)sys_malloc(dim_size); - memset(dims, 0, sizeof(int)*dim_size); - for(int i = 0; i < dim_size; ++i) + memset(dims, 0, sizeof(int) * dim_size); + for (int i = 0; i < dim_size; ++i) { dims[i] = shape.shape().dim(i).size(); } @@ -266,7 +266,7 @@ int tensorflow_serializer::set_graph_input(ir_graph_t* graph) { tensorflow::AttrValue value; const tensorflow::NodeDef* node_def = tf_node->pb_defs[pb_defs_cnt - 1]; - if(GetAttrValue(node_def, "value", value)) + if (GetAttrValue(node_def, "value", value)) { const tensorflow::TensorProto& tf_tensor = value.tensor(); @@ -276,32 +276,32 @@ int tensorflow_serializer::set_graph_input(ir_graph_t* graph) int dim_num = GetTensorContentAndDim(tf_tensor, &dims, &mem_ptr, layout); int mem_size = 1; - for(int i = 0; i < dim_num; i++) + for (int i = 0; i < dim_num; i++) mem_size *= dims[i]; - ir_tensor->data = (float*)malloc(sizeof(float)*mem_size); + ir_tensor->data = (float*)malloc(sizeof(float) * mem_size); ir_tensor->tensor_type = TENSOR_TYPE_CONST; // tensor->data = mem_ptr; float* tmp = (float*)mem_ptr; float* tr_tmp = (float*)ir_tensor->data; - for(int i = 0; i < mem_size; i++) + for (int i = 0; i < mem_size; i++) tr_tmp[i] = tmp[i]; - int* reshape_dim = ( int* )mem_ptr; - for(int i = 0; i < tf_dims[0]; i++) + int* reshape_dim = (int*)mem_ptr; + for (int i = 0; i < tf_dims[0]; i++) { dims[i] = reshape_dim[i]; } - for(unsigned int i = 0; i < tf_dims[0]; i++) + for (unsigned int i = 0; i < tf_dims[0]; i++) { - if(dims[i] == -1) + if (dims[i] == -1) dims[i] = 1; } free(mem_ptr); set_ir_tensor_shape(ir_tensor, dims, tf_dims[0]); } } - ir_node_t* node = create_ir_node(graph, tf_node->name.c_str(), OP_INPUT, OP_VERSION); + ir_node_t* node = create_ir_node(graph, tf_node->name.c_str(), OP_INPUT, OP_VERSION); int tensor_id = get_ir_tensor_index_from_name(graph, tf_node->name.c_str()); @@ -323,7 +323,7 @@ int tensorflow_serializer::construct_graph() std::unordered_map node_map; /* first scan, setup all nodes */ - for(int i = 0; i < node_number; i++) + for (int i = 0; i < node_number; i++) { const tensorflow::NodeDef& node_param = tf_net.node(i); @@ -340,30 +340,30 @@ int tensorflow_serializer::construct_graph() } /* the second scan, setup connections */ - for(int i = 0; i < node_number; i++) + for (int i = 0; i < node_number; i++) { const tensorflow::NodeDef& node_param = tf_net.node(i); const std::string& name = node_param.name(); TFNode* cur_node = node_map[name]; - for(int j = 0; j < node_param.input_size(); j++) + for (int j = 0; j < node_param.input_size(); j++) { const std::string& input_name = node_param.input(j); std::string::size_type pos = input_name.find(":"); std::string cleanup_name; - if(pos == std::string::npos) + if (pos == std::string::npos) pos = input_name.size(); - if(input_name[0] == '^') + if (input_name[0] == '^') cleanup_name = input_name.substr(1, pos); else cleanup_name = input_name.substr(0, pos); TFNode* input_node = node_map[cleanup_name]; - if(input_node == nullptr) + if (input_node == nullptr) { TLOG_ERR("cannot find input: %s for node: %s \n", input_name.c_str(), name.c_str()); return false; @@ -379,21 +379,21 @@ int DisconnectNode(TFNode* cur_node) { TFNode* input_node; - for(unsigned int i = 0; i < cur_node->inputs.size(); i++) + for (unsigned int i = 0; i < cur_node->inputs.size(); i++) { input_node = cur_node->inputs[i]; auto ir = input_node->outputs.begin(); - while(ir != input_node->outputs.end()) + while (ir != input_node->outputs.end()) { - if(*ir != cur_node) + if (*ir != cur_node) ir++; else break; } - if(ir == input_node->outputs.end()) + if (ir == input_node->outputs.end()) { TLOG_ERR("ERROR on node connection!!\n"); } @@ -405,21 +405,21 @@ int DisconnectNode(TFNode* cur_node) TFNode* output_node; - for(unsigned int i = 0; i < cur_node->outputs.size(); i++) + for (unsigned int i = 0; i < cur_node->outputs.size(); i++) { output_node = cur_node->outputs[i]; auto ir = output_node->inputs.begin(); - while(ir != output_node->inputs.end()) + while (ir != output_node->inputs.end()) { - if(*ir != cur_node) + if (*ir != cur_node) ir++; else break; } - if(ir == output_node->inputs.end()) + if (ir == output_node->inputs.end()) { TLOG_ERR("ERROR on node connection!!\n"); } @@ -436,15 +436,15 @@ int tensorflow_serializer::MergeParentNode(TFNode* base_node, TFNode* parent_nod auto input_ir = base_node->inputs.begin(); - while(input_ir != base_node->inputs.end()) + while (input_ir != base_node->inputs.end()) { - if(*input_ir == parent_node) + if (*input_ir == parent_node) break; input_ir++; } - if(parent_node->inputs.size() == 1) + if (parent_node->inputs.size() == 1) { *input_ir = parent_node->inputs[0]; } @@ -458,11 +458,11 @@ int tensorflow_serializer::MergeParentNode(TFNode* base_node, TFNode* parent_nod /* setup the outputs of parent node's parent */ - for(auto node : parent_node->inputs) + for (auto node : parent_node->inputs) { - for(unsigned int i = 0; i < node->outputs.size(); i++) + for (unsigned int i = 0; i < node->outputs.size(); i++) { - if(node->outputs[i] == parent_node) + if (node->outputs[i] == parent_node) { node->outputs[i] = base_node; break; @@ -474,17 +474,17 @@ int tensorflow_serializer::MergeParentNode(TFNode* base_node, TFNode* parent_nod auto output_ir = parent_node->outputs.begin(); - while(output_ir != parent_node->outputs.end()) + while (output_ir != parent_node->outputs.end()) { TFNode* node = *output_ir; - if(node != base_node) + if (node != base_node) { base_node->outputs.push_back(node); - for(unsigned int i = 0; i < node->inputs.size(); i++) + for (unsigned int i = 0; i < node->inputs.size(); i++) { - if(node->inputs[i] == parent_node) + if (node->inputs[i] == parent_node) { node->inputs[i] = base_node; break; @@ -509,19 +509,19 @@ int tensorflow_serializer::MergeParentNode(TFNode* base_node, TFNode* parent_nod bool CheckComposedBNAdd(TFNode* cur_node) { - if(cur_node->op != "Add") + if (cur_node->op != "Add") return false; TFNode* input0 = cur_node->inputs[0]; TFNode* input1 = cur_node->inputs[1]; - if(input0->op != "Mul" || input1->op != "Sub") + if (input0->op != "Mul" || input1->op != "Sub") return false; /* further check: /add_1 int name */ - if(cur_node->name.find("/add_1") != std::string::npos) + if (cur_node->name.find("/add_1") != std::string::npos) { - if(input0->name.find("/mul_1") != std::string::npos || input1->name.find("/mul_1") != std::string::npos) + if (input0->name.find("/mul_1") != std::string::npos || input1->name.find("/mul_1") != std::string::npos) cur_node->BNAddType = 1; else cur_node->BNAddType = 0; @@ -536,20 +536,20 @@ int tensorflow_serializer::BNRecursiveInputMerge(TFNode* node) { bool mul_1_node = false; bool mul_node = false; - if(node->name.find("/mul") != std::string::npos) + if (node->name.find("/mul") != std::string::npos) { - if(node->BNAddType == 1) + if (node->BNAddType == 1) { - if(node->name.find("/mul_1") != std::string::npos) + if (node->name.find("/mul_1") != std::string::npos) { mul_1_node = true; } - else if(node->name.find("/mul_2") == std::string::npos) + else if (node->name.find("/mul_2") == std::string::npos) { // disconnect the connection between mul and mul2 auto ir = node->outputs.begin(); - if((*ir)->name.find("/mul2") == std::string::npos) + if ((*ir)->name.find("/mul2") == std::string::npos) ir++; TFNode* mul2_node = *ir; @@ -558,7 +558,7 @@ int tensorflow_serializer::BNRecursiveInputMerge(TFNode* node) ir = mul2_node->inputs.begin(); - if((*ir)->name.find("/mul") == std::string::npos) + if ((*ir)->name.find("/mul") == std::string::npos) ir++; mul2_node->inputs.erase(ir); @@ -566,15 +566,15 @@ int tensorflow_serializer::BNRecursiveInputMerge(TFNode* node) } else { - if(node->name.find("/mul_1") != std::string::npos) + if (node->name.find("/mul_1") != std::string::npos) { // disconnect the connection between add_1 mul_1 auto ir = node->inputs.begin(); - if((*ir)->name.find("/add_1") == std::string::npos) + if ((*ir)->name.find("/add_1") == std::string::npos) ir++; - if((*ir)->name.find("/add_1") != std::string::npos) + if ((*ir)->name.find("/add_1") != std::string::npos) { TFNode* Rsqrt_node = *ir; @@ -582,7 +582,7 @@ int tensorflow_serializer::BNRecursiveInputMerge(TFNode* node) ir = Rsqrt_node->outputs.begin(); - if((*ir)->name.find("/mul_1") == std::string::npos) + if ((*ir)->name.find("/mul_1") == std::string::npos) ir++; Rsqrt_node->outputs.erase(ir); @@ -598,16 +598,16 @@ int tensorflow_serializer::BNRecursiveInputMerge(TFNode* node) int orig_input_size = node->inputs.size(); std::vector input_cpy = node->inputs; - for(int i = 0; i < orig_input_size; i++) + for (int i = 0; i < orig_input_size; i++) { - if(mul_node && i == 0) + if (mul_node && i == 0) continue; - if(mul_1_node && i == 0) + if (mul_1_node && i == 0) continue; TFNode* input_node = input_cpy[i]; input_node->BNAddType = node->BNAddType; - if(input_node->op == "Const") + if (input_node->op == "Const") continue; BNRecursiveInputMerge(input_node); @@ -625,11 +625,11 @@ int tensorflow_serializer::FuseComposedBN(TFNode* cur_node) /* skip to create static node for add/y */ - for(unsigned int i = 0; i < cur_node->inputs.size(); i++) + for (unsigned int i = 0; i < cur_node->inputs.size(); i++) { TFNode* node = cur_node->inputs[i]; - if(node->name.find("/add/y") != std::string::npos) + if (node->name.find("/add/y") != std::string::npos) node->no_static_node = true; } } @@ -637,14 +637,14 @@ int tensorflow_serializer::MergeChildNode(TFNode* base_node, TFNode* child_node) { auto output_ir = base_node->outputs.begin(); - while(output_ir != base_node->outputs.end()) + while (output_ir != base_node->outputs.end()) { - if(*output_ir == child_node) + if (*output_ir == child_node) break; output_ir++; } - if(child_node->outputs.size() == 1) + if (child_node->outputs.size() == 1) { *output_ir = child_node->outputs[0]; } @@ -654,11 +654,11 @@ int tensorflow_serializer::MergeChildNode(TFNode* base_node, TFNode* child_node) base_node->outputs.insert(base_node->outputs.end(), child_node->outputs.begin(), child_node->outputs.end()); } - for(auto node : child_node->outputs) + for (auto node : child_node->outputs) { - for(unsigned int i = 0; i < node->inputs.size(); i++) + for (unsigned int i = 0; i < node->inputs.size(); i++) { - if(node->inputs[i] == child_node) + if (node->inputs[i] == child_node) { node->inputs[i] = base_node; break; @@ -668,17 +668,17 @@ int tensorflow_serializer::MergeChildNode(TFNode* base_node, TFNode* child_node) auto ir = child_node->inputs.begin(); - while(ir != child_node->inputs.end()) + while (ir != child_node->inputs.end()) { TFNode* node = *ir; - if(node != base_node) + if (node != base_node) { base_node->inputs.push_back(node); - for(unsigned int i = 0; i < node->outputs.size(); i++) + for (unsigned int i = 0; i < node->outputs.size(); i++) { - if(node->outputs[i] == child_node) + if (node->outputs[i] == child_node) { node->outputs[i] = base_node; break; @@ -699,25 +699,24 @@ int tensorflow_serializer::MergeChildNode(TFNode* base_node, TFNode* child_node) return 0; } - void tensorflow_serializer::CleanupResizeNearestNeighbor() { auto ir = tf_graph.seq_nodes.begin(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if(cur_node->op == "ResizeNearestNeighbor") + if (cur_node->op == "ResizeNearestNeighbor") { TFNode* data_node = cur_node->inputs[0]; TFNode* data_shape_node = nullptr; - for(unsigned int i = 0; i < data_node->outputs.size(); i++) + for (unsigned int i = 0; i < data_node->outputs.size(); i++) { data_shape_node = data_node->outputs[i]; - if(data_shape_node->op == "Shape") + if (data_shape_node->op == "Shape") break; } @@ -733,19 +732,18 @@ void tensorflow_serializer::CleanupResizeNearestNeighbor() } } - void tensorflow_serializer::MergeReluMinimum() { - for(auto ir = tf_graph.seq_nodes.begin(); ir != tf_graph.seq_nodes.end(); ir++) + for (auto ir = tf_graph.seq_nodes.begin(); ir != tf_graph.seq_nodes.end(); ir++) { TFNode* cur_node = *ir; - if(cur_node->inputs.size() == 0) + if (cur_node->inputs.size() == 0) continue; TFNode* input0 = cur_node->inputs[0]; - if(cur_node->op == "Minimum" && input0->op == "Relu") + if (cur_node->op == "Minimum" && input0->op == "Relu") { TFNode* const_node = cur_node->inputs[1]; @@ -763,18 +761,18 @@ int tensorflow_serializer::optimize_graph() /* first clean up the predictions module of TF */ auto ir = tf_graph.seq_nodes.begin(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if(cur_node->op == "Reshape") + if (cur_node->op == "Reshape") { /* Reshape should have two inputs */ TFNode* input_node0 = cur_node->inputs[0]; TFNode* input_node1 = cur_node->inputs[1]; - if(input_node0->op == "Softmax" || input_node1->op == "Softmax") + if (input_node0->op == "Softmax" || input_node1->op == "Softmax") { DisconnectNode(cur_node); ir = tf_graph.seq_nodes.erase(ir); @@ -783,16 +781,16 @@ int tensorflow_serializer::optimize_graph() } TFNode* output_node = cur_node->outputs[0]; - if(NULL == output_node) + if (NULL == output_node) continue; - if(output_node->op == "Softmax" || output_node->op == "MatMul") + if (output_node->op == "Softmax" || output_node->op == "MatMul") { TFNode* input_node0 = cur_node->inputs[0]; TFNode* input_node1 = cur_node->inputs[1]; TFNode* input_node; - if(input_node0->op == "Const") + if (input_node0->op == "Const") { DisconnectNode(input_node0); input_node = input_node1; @@ -817,26 +815,26 @@ int tensorflow_serializer::optimize_graph() /* remove the squeeze node and identity */ ir = tf_graph.seq_nodes.begin(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if(cur_node->op == "Squeeze") + if (cur_node->op == "Squeeze") { TFNode* softmax_node = nullptr; TFNode* shape_node = nullptr; - for(unsigned int j = 0; j < cur_node->outputs.size(); j++) + for (unsigned int j = 0; j < cur_node->outputs.size(); j++) { - if(cur_node->outputs[j]->op == "Softmax") + if (cur_node->outputs[j]->op == "Softmax") softmax_node = cur_node->outputs[j]; - else if(cur_node->outputs[j]->op == "Shape") + else if (cur_node->outputs[j]->op == "Shape") shape_node = cur_node->outputs[j]; } - if(softmax_node) + if (softmax_node) { - if(shape_node) + if (shape_node) DisconnectNode(shape_node); TFNode* input_node = cur_node->inputs[0]; @@ -846,7 +844,7 @@ int tensorflow_serializer::optimize_graph() continue; } - if(cur_node->outputs.size() == 1 && softmax_node == nullptr) + if (cur_node->outputs.size() == 1 && softmax_node == nullptr) { TFNode* child_node = cur_node->outputs[0]; @@ -857,7 +855,7 @@ int tensorflow_serializer::optimize_graph() } } - if(cur_node->op == "Identity") + if (cur_node->op == "Identity") { TFNode* input_node = cur_node->inputs[0]; MergeChildNode(input_node, cur_node); @@ -867,22 +865,22 @@ int tensorflow_serializer::optimize_graph() continue; } - if(cur_node->op == "ConcatV2") + if (cur_node->op == "ConcatV2") { TFNode* axis_node = nullptr; - for(unsigned int i = 0; i < cur_node->inputs.size(); i++) + for (unsigned int i = 0; i < cur_node->inputs.size(); i++) { TFNode* check_node = cur_node->inputs[i]; - if(check_node->op == "Const") + if (check_node->op == "Const") { axis_node = check_node; break; } } - if(axis_node) + if (axis_node) { cur_node->pb_defs.push_back(axis_node->pb_defs[0]); DisconnectNode(axis_node); @@ -896,15 +894,15 @@ int tensorflow_serializer::optimize_graph() ir = tf_graph.seq_nodes.begin(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if(cur_node->op == "FIFOQueueV2") + if (cur_node->op == "FIFOQueueV2") { TFNode* queue_node = cur_node->outputs[0]; - if(queue_node->op == "QueueDequeueManyV2") + if (queue_node->op == "QueueDequeueManyV2") { MergeParentNode(queue_node, queue_node->inputs[1]); } @@ -920,16 +918,16 @@ int tensorflow_serializer::optimize_graph() /* remove ExpandDims */ ir = tf_graph.seq_nodes.begin(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if(cur_node->op == "ExpandDims") + if (cur_node->op == "ExpandDims") { TFNode* input0 = cur_node->inputs[0]; TFNode* input1 = cur_node->inputs[1]; - if(input0->op == "Constant" && input1->op == "Const") + if (input0->op == "Constant" && input1->op == "Const") { TFNode* input1 = cur_node->inputs[1]; TFNode* child_node = cur_node->outputs[0]; @@ -942,7 +940,7 @@ int tensorflow_serializer::optimize_graph() } else { - if(input1->op == "Const") + if (input1->op == "Const") DisconnectNode(input1); else DisconnectNode(input0); @@ -964,15 +962,15 @@ int tensorflow_serializer::optimize_graph() /* merge biasadd and conv */ ir = tf_graph.seq_nodes.begin(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if(cur_node->op == "Conv2D" || cur_node->op == "DepthwiseConv2dNative" || cur_node->op == "MatMul") + if (cur_node->op == "Conv2D" || cur_node->op == "DepthwiseConv2dNative" || cur_node->op == "MatMul") { TFNode* output_node = cur_node->outputs[0]; - if(output_node->op == "BiasAdd" || output_node->op == "Add") + if (output_node->op == "BiasAdd" || output_node->op == "Add") { MergeChildNode(cur_node, output_node); } @@ -985,11 +983,11 @@ int tensorflow_serializer::optimize_graph() ir = tf_graph.seq_nodes.begin(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if(CheckComposedBNAdd(cur_node)) + if (CheckComposedBNAdd(cur_node)) FuseComposedBN(cur_node); ir++; } @@ -1002,21 +1000,21 @@ int tensorflow_serializer::optimize_graph() MergeReluMinimum(); /* merge input node and reshape */ ir = tf_graph.seq_nodes.begin(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if(cur_node->op == "Reshape") + if (cur_node->op == "Reshape") { /* Reshape should have two inputs */ TFNode* input_node0 = cur_node->inputs[0]; TFNode* input_node1 = cur_node->inputs[1]; - if(input_node0->op == "Placeholder" || input_node1->op == "Placeholder") + if (input_node0->op == "Placeholder" || input_node1->op == "Placeholder") { TFNode* input_node; TFNode* const_node; - if(input_node0->op == "Const") + if (input_node0->op == "Const") { const_node = input_node0; input_node = input_node1; @@ -1043,15 +1041,15 @@ int tensorflow_serializer::optimize_graph() ir = tf_graph.seq_nodes.begin(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if(cur_node->op == "StridedSlice") + if (cur_node->op == "StridedSlice") { /* check if input0 is "shape" */ TFNode* input_node = cur_node->inputs[0]; - if(input_node->op == "Shape") + if (input_node->op == "Shape") { /* here we go */ DisconnectNode(cur_node); @@ -1067,16 +1065,16 @@ int tensorflow_serializer::optimize_graph() ir = tf_graph.seq_nodes.begin(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if(cur_node->op == "Conv2D" || cur_node->op == "DepthwiseConv2dNative") + if (cur_node->op == "Conv2D" || cur_node->op == "DepthwiseConv2dNative") { /* check if input is pad or not */ TFNode* input_node = cur_node->inputs[0]; - if(input_node->op == "Pad") + if (input_node->op == "Pad") { TFNode* padding_args = input_node->inputs[1]; @@ -1092,10 +1090,10 @@ int tensorflow_serializer::optimize_graph() /*remove ArgMax node */ ir = tf_graph.seq_nodes.begin(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if(cur_node->op == "ArgMax") + if (cur_node->op == "ArgMax") { DisconnectNode(cur_node); tf_graph.seq_nodes.erase(ir); @@ -1110,11 +1108,11 @@ int tensorflow_serializer::optimize_graph() ir = tf_graph.seq_nodes.begin(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if(cur_node->op == "Squeeze" && cur_node->outputs.empty()) + if (cur_node->op == "Squeeze" && cur_node->outputs.empty()) { DisconnectNode(cur_node); break; @@ -1126,11 +1124,11 @@ int tensorflow_serializer::optimize_graph() ir = tf_graph.seq_nodes.begin(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if(cur_node->inputs.size() == 0 && cur_node->outputs.size() == 0) + if (cur_node->inputs.size() == 0 && cur_node->outputs.size() == 0) { ir = tf_graph.seq_nodes.erase(ir); delete cur_node; @@ -1142,18 +1140,17 @@ int tensorflow_serializer::optimize_graph() /* remove no input but not placeholder/const nodes */ ir = tf_graph.seq_nodes.begin(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* cur_node = *ir; - if(cur_node->inputs.size() == 0 && cur_node->op != "Const" && cur_node->op != "Placeholder" && - cur_node->op != "FIFOQueueV2") + if (cur_node->inputs.size() == 0 && cur_node->op != "Const" && cur_node->op != "Placeholder" && cur_node->op != "FIFOQueueV2") { DisconnectNode(cur_node); tf_graph.seq_nodes.erase(ir); delete cur_node; - ir = tf_graph.seq_nodes.begin(); // restart + ir = tf_graph.seq_nodes.begin(); // restart } else ir++; @@ -1162,7 +1159,6 @@ int tensorflow_serializer::optimize_graph() return 0; } - int tensorflow_serializer::FindRNNScope(std::string& rnn_scope) { std::string rnn_node; @@ -1171,19 +1167,19 @@ int tensorflow_serializer::FindRNNScope(std::string& rnn_scope) int rnn_type = -1; - for(unsigned int i = 0; i < tf_graph.seq_nodes.size(); i++) + for (unsigned int i = 0; i < tf_graph.seq_nodes.size(); i++) { TFNode* node = tf_graph.seq_nodes.at(i); std::string& name = node->name; while_pos = name.find("while"); - if(while_pos == std::string::npos) + if (while_pos == std::string::npos) continue; std::string::size_type cell_pos = name.find("lstm_cell", while_pos); - if(cell_pos != std::string::npos) + if (cell_pos != std::string::npos) { rnn_node = node->name; rnn_type = TF_RNN_LSTM; @@ -1192,7 +1188,7 @@ int tensorflow_serializer::FindRNNScope(std::string& rnn_scope) cell_pos = name.find("gru_cell", while_pos); - if(cell_pos != std::string::npos) + if (cell_pos != std::string::npos) { rnn_node = node->name; rnn_type = TF_RNN_GRU; @@ -1201,7 +1197,7 @@ int tensorflow_serializer::FindRNNScope(std::string& rnn_scope) cell_pos = name.find("basic_lstm_cell", while_pos); - if(cell_pos != std::string::npos) + if (cell_pos != std::string::npos) { rnn_node = node->name; rnn_type = TF_RNN_BASIC_LSTM; @@ -1210,7 +1206,7 @@ int tensorflow_serializer::FindRNNScope(std::string& rnn_scope) cell_pos = name.find("basic_rnn_cell", while_pos); - if(cell_pos != std::string::npos) + if (cell_pos != std::string::npos) { rnn_node = node->name; rnn_type = TF_RNN_BASIC_RNN; @@ -1218,7 +1214,7 @@ int tensorflow_serializer::FindRNNScope(std::string& rnn_scope) } } - if(rnn_node.empty()) + if (rnn_node.empty()) return -1; std::string rnn_layer = rnn_node.substr(0, while_pos - 1); @@ -1233,36 +1229,36 @@ void tensorflow_serializer::ParseLSTMGraph(LSTMNode* lstm_node, std::setinputs.size(); i++) + for (unsigned int i = 0; i < lstm_node->inputs.size(); i++) { TFNode* node = lstm_node->inputs[i]; - if(node->op != "Const") + if (node->op != "Const") continue; // node->no_static_node=true; //do not automatically create Static Node - if(node->name.find("lstm_cell/kernel") != std::string::npos) + if (node->name.find("lstm_cell/kernel") != std::string::npos) { lstm_node->kernel = node; } - else if(node->name.find("lstm_cell/bias") != std::string::npos) + else if (node->name.find("lstm_cell/bias") != std::string::npos) { lstm_node->bias = node; } - else if(node->name.find("lstm_cell/w_f_diag") != std::string::npos) + else if (node->name.find("lstm_cell/w_f_diag") != std::string::npos) { lstm_node->w_f_diag = node; } - else if(node->name.find("lstm_cell/w_o_diag") != std::string::npos) + else if (node->name.find("lstm_cell/w_o_diag") != std::string::npos) { lstm_node->w_o_diag = node; } - else if(node->name.find("lstm_cell/w_i_diag") != std::string::npos) + else if (node->name.find("lstm_cell/w_i_diag") != std::string::npos) { lstm_node->w_i_diag = node; } - else if(node->name.find("lstm_cell/projection/kernel") != std::string::npos) + else if (node->name.find("lstm_cell/projection/kernel") != std::string::npos) { lstm_node->projection = node; } @@ -1271,7 +1267,7 @@ void tensorflow_serializer::ParseLSTMGraph(LSTMNode* lstm_node, std::setname.size(); @@ -1279,11 +1275,11 @@ void tensorflow_serializer::ParseLSTMGraph(LSTMNode* lstm_node, std::setname.find(zero_name, name_len - zero_name.size()) != std::string::npos) + if (node->name.find(zero_name, name_len - zero_name.size()) != std::string::npos) lstm_node->init_c = node; - else if(node->name.find(zero1_name, name_len - zero1_name.size()) != std::string::npos) + else if (node->name.find(zero1_name, name_len - zero1_name.size()) != std::string::npos) lstm_node->init_h = node; - else if(node->name.find(forget_name, name_len - forget_name.size()) != std::string::npos) + else if (node->name.find(forget_name, name_len - forget_name.size()) != std::string::npos) lstm_node->forget_bias = node; rnn_ir++; @@ -1293,28 +1289,28 @@ void ParseGRUGraph(TFGraph& tf_graph, GRUNode* gru_node, std::set& rnn_ { /* parse input node */ - for(unsigned int i = 0; i < gru_node->inputs.size(); i++) + for (unsigned int i = 0; i < gru_node->inputs.size(); i++) { TFNode* node = gru_node->inputs[i]; - if(node->op != "Const") + if (node->op != "Const") continue; // node->no_static_node=true; //do not automatically create Static Node - if(node->name.find("gru_cell/gates/kernel") != std::string::npos) + if (node->name.find("gru_cell/gates/kernel") != std::string::npos) { gru_node->gate_kernel = node; } - else if(node->name.find("gru_cell/gates/bias") != std::string::npos) + else if (node->name.find("gru_cell/gates/bias") != std::string::npos) { gru_node->gate_bias = node; } - else if(node->name.find("gru_cell/candidate/kernel") != std::string::npos) + else if (node->name.find("gru_cell/candidate/kernel") != std::string::npos) { gru_node->candidate_kernel = node; } - else if(node->name.find("gru_cell/candidate/bias") != std::string::npos) + else if (node->name.find("gru_cell/candidate/bias") != std::string::npos) { gru_node->candidate_bias = node; } @@ -1323,13 +1319,13 @@ void ParseGRUGraph(TFGraph& tf_graph, GRUNode* gru_node, std::set& rnn_ auto rnn_ir = rnn_graph.begin(); auto rnn_ir_end = rnn_graph.end(); - while(rnn_ir != rnn_ir_end) + while (rnn_ir != rnn_ir_end) { TFNode* node = *rnn_ir; int name_len = node->name.size(); std::string zero_name = "GRUCellZeroState/zeros"; - if(node->name.find(zero_name, name_len - zero_name.size()) != std::string::npos) + if (node->name.find(zero_name, name_len - zero_name.size()) != std::string::npos) gru_node->init_h = node; rnn_ir++; @@ -1339,20 +1335,20 @@ void ParseRNNGraph(TFGraph& tf_graph, RNNNode* rnn_node, std::set& rnn_ { /* parse input node */ - for(unsigned int i = 0; i < rnn_node->inputs.size(); i++) + for (unsigned int i = 0; i < rnn_node->inputs.size(); i++) { TFNode* node = rnn_node->inputs[i]; - if(node->op != "Const") + if (node->op != "Const") continue; // node->no_static_node=true; //do not automatically create Static Node - if(node->name.find("basic_rnn_cell/kernel") != std::string::npos) + if (node->name.find("basic_rnn_cell/kernel") != std::string::npos) { rnn_node->kernel = node; } - else if(node->name.find("basic_rnn_cell/bias") != std::string::npos) + else if (node->name.find("basic_rnn_cell/bias") != std::string::npos) { rnn_node->bias = node; } @@ -1361,13 +1357,13 @@ void ParseRNNGraph(TFGraph& tf_graph, RNNNode* rnn_node, std::set& rnn_ auto rnn_ir = rnn_graph.begin(); auto rnn_ir_end = rnn_graph.end(); - while(rnn_ir != rnn_ir_end) + while (rnn_ir != rnn_ir_end) { TFNode* node = *rnn_ir; int name_len = node->name.size(); std::string zero_name = "BasicRNNCellZeroState/zeros"; - if(node->name.find(zero_name, name_len - zero_name.size()) != std::string::npos) + if (node->name.find(zero_name, name_len - zero_name.size()) != std::string::npos) rnn_node->init_h = node; rnn_ir++; @@ -1377,7 +1373,7 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) { // collect attributes according to rnn_type - if(rnn_type == TF_RNN_LSTM) + if (rnn_type == TF_RNN_LSTM) { LSTMNode* lstm_node = new LSTMNode(); @@ -1392,11 +1388,11 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) auto ir = tf_graph.seq_nodes.begin(); std::string::size_type prefix_len = rnn_scope.size(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* node = *ir; - if(node->name.find(rnn_scope.c_str(), 0, prefix_len) == std::string::npos) + if (node->name.find(rnn_scope.c_str(), 0, prefix_len) == std::string::npos) { ir++; continue; @@ -1411,23 +1407,23 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) auto rnn_ir = rnn_graph.begin(); auto rnn_end = rnn_graph.end(); - while(rnn_ir != rnn_end) + while (rnn_ir != rnn_end) { TFNode* node = *rnn_ir; - for(unsigned int i = 0; i < node->inputs.size(); i++) + for (unsigned int i = 0; i < node->inputs.size(); i++) { TFNode* input = node->inputs[i]; - if(!rnn_graph.count(input)) + if (!rnn_graph.count(input)) rnn_inputs.insert(input); } - for(unsigned int i = 0; i < node->outputs.size(); i++) + for (unsigned int i = 0; i < node->outputs.size(); i++) { TFNode* output = node->outputs[i]; - if(!rnn_graph.count(output)) + if (!rnn_graph.count(output)) rnn_outputs.insert(output); } @@ -1437,11 +1433,11 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) // insert lstm node auto seq_ir = tf_graph.seq_nodes.begin(); - while(seq_ir != tf_graph.seq_nodes.end()) + while (seq_ir != tf_graph.seq_nodes.end()) { TFNode* node = *seq_ir; - if(rnn_inputs.count(node)) + if (rnn_inputs.count(node)) { tf_graph.seq_nodes.insert(seq_ir, lstm_node); break; @@ -1454,21 +1450,21 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) auto set_ir = rnn_inputs.begin(); auto set_ir_end = rnn_inputs.end(); - while(set_ir != set_ir_end) + while (set_ir != set_ir_end) { TFNode* input_node = *set_ir; - for(unsigned int j = 0; j < input_node->outputs.size(); j++) + for (unsigned int j = 0; j < input_node->outputs.size(); j++) { TFNode* child_node = input_node->outputs[j]; - if(rnn_graph.count(child_node)) + if (rnn_graph.count(child_node)) input_node->outputs[j] = lstm_node; } lstm_node->inputs.push_back(input_node); - if(input_node->op == "Identity") + if (input_node->op == "Identity") { TFNode* parent_node = input_node->inputs[0]; @@ -1481,15 +1477,15 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) set_ir = rnn_outputs.begin(); set_ir_end = rnn_outputs.end(); - while(set_ir != set_ir_end) + while (set_ir != set_ir_end) { TFNode* output_node = *set_ir; - for(unsigned int j = 0; j < output_node->inputs.size(); j++) + for (unsigned int j = 0; j < output_node->inputs.size(); j++) { TFNode* parent_node = output_node->inputs[j]; - if(rnn_graph.count(parent_node)) + if (rnn_graph.count(parent_node)) output_node->inputs[j] = lstm_node; } @@ -1507,7 +1503,7 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) ParseLSTMGraph(lstm_node, rnn_graph); } - if(rnn_type == TF_RNN_BASIC_RNN) + if (rnn_type == TF_RNN_BASIC_RNN) { RNNNode* rnn_node = new RNNNode(); @@ -1523,11 +1519,11 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) auto ir = tf_graph.seq_nodes.begin(); std::string::size_type prefix_len = rnn_scope.size(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* node = *ir; - if(node->name.find(rnn_scope.c_str(), 0, prefix_len) == std::string::npos) + if (node->name.find(rnn_scope.c_str(), 0, prefix_len) == std::string::npos) { ir++; continue; @@ -1542,23 +1538,23 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) auto rnn_ir = rnn_graph.begin(); auto rnn_end = rnn_graph.end(); - while(rnn_ir != rnn_end) + while (rnn_ir != rnn_end) { TFNode* node = *rnn_ir; - for(unsigned int i = 0; i < node->inputs.size(); i++) + for (unsigned int i = 0; i < node->inputs.size(); i++) { TFNode* input = node->inputs[i]; - if(!rnn_graph.count(input)) + if (!rnn_graph.count(input)) rnn_inputs.insert(input); } - for(unsigned int i = 0; i < node->outputs.size(); i++) + for (unsigned int i = 0; i < node->outputs.size(); i++) { TFNode* output = node->outputs[i]; - if(!rnn_graph.count(output)) + if (!rnn_graph.count(output)) rnn_outputs.insert(output); } @@ -1568,11 +1564,11 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) // insert rnn node auto seq_ir = tf_graph.seq_nodes.begin(); - while(seq_ir != tf_graph.seq_nodes.end()) + while (seq_ir != tf_graph.seq_nodes.end()) { TFNode* node = *seq_ir; - if(rnn_inputs.count(node)) + if (rnn_inputs.count(node)) { tf_graph.seq_nodes.insert(seq_ir, rnn_node); break; @@ -1585,21 +1581,21 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) auto set_ir = rnn_inputs.begin(); auto set_ir_end = rnn_inputs.end(); - while(set_ir != set_ir_end) + while (set_ir != set_ir_end) { TFNode* input_node = *set_ir; - for(unsigned int j = 0; j < input_node->outputs.size(); j++) + for (unsigned int j = 0; j < input_node->outputs.size(); j++) { TFNode* child_node = input_node->outputs[j]; - if(rnn_graph.count(child_node)) + if (rnn_graph.count(child_node)) input_node->outputs[j] = rnn_node; } rnn_node->inputs.push_back(input_node); - if(input_node->op == "Identity") + if (input_node->op == "Identity") { TFNode* parent_node = input_node->inputs[0]; @@ -1612,15 +1608,15 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) set_ir = rnn_outputs.begin(); set_ir_end = rnn_outputs.end(); - while(set_ir != set_ir_end) + while (set_ir != set_ir_end) { TFNode* output_node = *set_ir; - for(unsigned int j = 0; j < output_node->inputs.size(); j++) + for (unsigned int j = 0; j < output_node->inputs.size(); j++) { TFNode* parent_node = output_node->inputs[j]; - if(rnn_graph.count(parent_node)) + if (rnn_graph.count(parent_node)) output_node->inputs[j] = rnn_node; } @@ -1637,7 +1633,7 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) ParseRNNGraph(tf_graph, rnn_node, rnn_graph); } - if(rnn_type == TF_RNN_GRU) + if (rnn_type == TF_RNN_GRU) { GRUNode* gru_node = new GRUNode(); @@ -1653,11 +1649,11 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) auto ir = tf_graph.seq_nodes.begin(); std::string::size_type prefix_len = rnn_scope.size(); - while(ir != tf_graph.seq_nodes.end()) + while (ir != tf_graph.seq_nodes.end()) { TFNode* node = *ir; - if(node->name.find(rnn_scope.c_str(), 0, prefix_len) == std::string::npos) + if (node->name.find(rnn_scope.c_str(), 0, prefix_len) == std::string::npos) { ir++; continue; @@ -1672,23 +1668,23 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) auto rnn_ir = rnn_graph.begin(); auto rnn_end = rnn_graph.end(); - while(rnn_ir != rnn_end) + while (rnn_ir != rnn_end) { TFNode* node = *rnn_ir; - for(unsigned int i = 0; i < node->inputs.size(); i++) + for (unsigned int i = 0; i < node->inputs.size(); i++) { TFNode* input = node->inputs[i]; - if(!rnn_graph.count(input)) + if (!rnn_graph.count(input)) rnn_inputs.insert(input); } - for(unsigned int i = 0; i < node->outputs.size(); i++) + for (unsigned int i = 0; i < node->outputs.size(); i++) { TFNode* output = node->outputs[i]; - if(!rnn_graph.count(output)) + if (!rnn_graph.count(output)) rnn_outputs.insert(output); } @@ -1698,11 +1694,11 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) // insert rnn node auto seq_ir = tf_graph.seq_nodes.begin(); - while(seq_ir != tf_graph.seq_nodes.end()) + while (seq_ir != tf_graph.seq_nodes.end()) { TFNode* node = *seq_ir; - if(rnn_inputs.count(node)) + if (rnn_inputs.count(node)) { tf_graph.seq_nodes.insert(seq_ir, gru_node); break; @@ -1715,21 +1711,21 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) auto set_ir = rnn_inputs.begin(); auto set_ir_end = rnn_inputs.end(); - while(set_ir != set_ir_end) + while (set_ir != set_ir_end) { TFNode* input_node = *set_ir; - for(unsigned int j = 0; j < input_node->outputs.size(); j++) + for (unsigned int j = 0; j < input_node->outputs.size(); j++) { TFNode* child_node = input_node->outputs[j]; - if(rnn_graph.count(child_node)) + if (rnn_graph.count(child_node)) input_node->outputs[j] = gru_node; } gru_node->inputs.push_back(input_node); - if(input_node->op == "Identity") + if (input_node->op == "Identity") { TFNode* parent_node = input_node->inputs[0]; @@ -1742,15 +1738,15 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) set_ir = rnn_outputs.begin(); set_ir_end = rnn_outputs.end(); - while(set_ir != set_ir_end) + while (set_ir != set_ir_end) { TFNode* output_node = *set_ir; - for(unsigned int j = 0; j < output_node->inputs.size(); j++) + for (unsigned int j = 0; j < output_node->inputs.size(); j++) { TFNode* parent_node = output_node->inputs[j]; - if(rnn_graph.count(parent_node)) + if (rnn_graph.count(parent_node)) output_node->inputs[j] = gru_node; } @@ -1771,11 +1767,11 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) // cleanup zero in/zero out node auto seq_ir = tf_graph.seq_nodes.begin(); - while(seq_ir != tf_graph.seq_nodes.end()) + while (seq_ir != tf_graph.seq_nodes.end()) { TFNode* node = *seq_ir; - if(node->inputs.size() == 0 && node->outputs.size() == 0) + if (node->inputs.size() == 0 && node->outputs.size() == 0) { delete node; seq_ir = tf_graph.seq_nodes.erase(seq_ir); @@ -1788,13 +1784,13 @@ void tensorflow_serializer::StripRNNScope(std::string& rnn_scope, int rnn_type) } int tensorflow_serializer::optimize_rnn() { - while(1) + while (1) { std::string rnn_scope; int rnn_type = FindRNNScope(rnn_scope); - if(rnn_scope.empty()) + if (rnn_scope.empty()) break; StripRNNScope(rnn_scope, rnn_type); @@ -1803,7 +1799,6 @@ int tensorflow_serializer::optimize_rnn() return true; } - int tensorflow_serializer::generate_graph(ir_graph_t* graph) { int node_number = tf_graph.seq_nodes.size(); @@ -1811,45 +1806,44 @@ int tensorflow_serializer::generate_graph(ir_graph_t* graph) bool debug_graph = false; const char* debug_env = std::getenv("DEBUG_TF"); - if((debug_env) && (debug_env[0] == '1')) + if ((debug_env) && (debug_env[0] == '1')) { debug_graph = true; } // first: create all tensor node - for(i = 0; i < node_number; i++) + for (i = 0; i < node_number; i++) { TFNode* tf_node = tf_graph.seq_nodes[i]; - if(debug_graph) + if (debug_graph) { std::cout << i << "\t" << tf_node->op << "\t" << tf_node->name << "\n"; } - if(tf_node->no_static_node) + if (tf_node->no_static_node) continue; - if(tf_node->op == "Placeholder") + if (tf_node->op == "Placeholder") continue; - - if(tf_node->op == "Const") + if (tf_node->op == "Const") { load_const_tensor(tf_node, graph); continue; } - } + } - for(int i = 0; i < (int)tf_graph.seq_nodes.size(); i++) + for (int i = 0; i < (int)tf_graph.seq_nodes.size(); i++) { TFNode* tf_node = tf_graph.seq_nodes[i]; - if(tf_node->op == "Placeholder" || tf_node->op == "Const") + if (tf_node->op == "Placeholder" || tf_node->op == "Const") continue; ir_node_t* ir_node = nullptr; int node_idx = get_ir_node_index_from_name(graph, tf_node->name.c_str()); - if(node_idx < 0) + if (node_idx < 0) { ir_node = create_ir_node(graph, tf_node->name.c_str(), op_load_map[tf_node->op].first, OP_VERSION); } @@ -1857,30 +1851,30 @@ int tensorflow_serializer::generate_graph(ir_graph_t* graph) { ir_node = get_ir_graph_node(graph, node_idx); } - for(int in = 0; in < tf_node->inputs.size(); in++) + for (int in = 0; in < tf_node->inputs.size(); in++) { TFNode* node = tf_node->inputs[in]; int tensor_idx = get_ir_tensor_index_from_name(graph, node->name.c_str()); ir_tensor_t* tensor = nullptr; - if(node->name == "Placeholder") + if (node->name == "Placeholder") { continue; } - if(tensor_idx < 0) - tensor = create_ir_tensor(graph, tf_node->name.c_str(),TENGINE_DT_FP32 ); + if (tensor_idx < 0) + tensor = create_ir_tensor(graph, tf_node->name.c_str(), TENGINE_DT_FP32); else tensor = get_ir_graph_tensor(graph, tensor_idx); set_ir_node_input_tensor(ir_node, in, tensor); input_tensors.push_back(node->name.c_str()); } - for(int out = 0; out < tf_node->outputs.size(); out++) + for (int out = 0; out < tf_node->outputs.size(); out++) { TFNode* node = tf_node->outputs[out]; int tensor_idx = get_ir_tensor_index_from_name(graph, node->name.c_str()); ir_tensor_t* tensor = nullptr; - if(tensor_idx < 0) - tensor = create_ir_tensor(graph, tf_node->name.c_str(),TENGINE_DT_FP32 ); + if (tensor_idx < 0) + tensor = create_ir_tensor(graph, tf_node->name.c_str(), TENGINE_DT_FP32); else tensor = get_ir_graph_tensor(graph, tensor_idx); set_ir_node_output_tensor(ir_node, out, tensor); @@ -1893,9 +1887,9 @@ int tensorflow_serializer::generate_graph(ir_graph_t* graph) fprintf(stderr, "load op %s func failed in node %s .\n", tf_node->op.c_str(), tf_node->name.c_str()); return -1; } - } + } - if(i < node_number) + if (i < node_number) return -1; return 0; @@ -1922,11 +1916,11 @@ int tensorflow_serializer::set_graph_output(ir_graph_t* graph) { int tensor_id = get_ir_tensor_index_from_name(graph, graph_outputs[i].c_str()); ir_tensor_t* tensor = nullptr; - if(tensor_id < 0) - tensor = create_ir_tensor(graph, graph_outputs[i].c_str(),TENGINE_DT_FP32 ); + if (tensor_id < 0) + tensor = create_ir_tensor(graph, graph_outputs[i].c_str(), TENGINE_DT_FP32); else tensor = get_ir_graph_tensor(graph, tensor_id); - int node_idx = get_ir_node_index_from_name(graph,graph_outputs[i].c_str() ); + int node_idx = get_ir_node_index_from_name(graph, graph_outputs[i].c_str()); ir_node_t* node = get_ir_graph_node(graph, node_idx); set_ir_node_output_tensor(node, 0, tensor); output_nodes.push_back(node->index); @@ -1964,7 +1958,6 @@ int tensorflow_serializer::load_graph(ir_graph_t* graph) return 0; } - int tensorflow_serializer::load_model(ir_graph_t* graph, std::string model_file) { register_op_load(); @@ -2008,28 +2001,28 @@ int load_pool(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* const tensorflow::NodeDef* node_def = tf_node->pb_defs[0]; tensorflow::AttrValue value; - if(GetAttrValue(node_def, "ksize", value)) + if (GetAttrValue(node_def, "ksize", value)) { param->kernel_h = value.list().i(1); param->kernel_w = value.list().i(2); } - if(GetAttrValue(node_def, "strides", value)) + if (GetAttrValue(node_def, "strides", value)) { param->stride_h = value.list().i(1); param->stride_w = value.list().i(2); } - if(GetAttrValue(node_def, "padding", value)) + if (GetAttrValue(node_def, "padding", value)) { - if(value.s() == "VALID") + if (value.s() == "VALID") { param->pad_h0 = 0; param->pad_h1 = 0; param->pad_w0 = 0; param->pad_w1 = 0; } - else if(value.s() == "SAME") + else if (value.s() == "SAME") { param->pad_h0 = -1; param->pad_h1 = -1; @@ -2038,11 +2031,11 @@ int load_pool(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* } } - if(tf_node->op == "AvgPool") + if (tf_node->op == "AvgPool") { param->pool_method = 1; } - else if(tf_node->op == "MaxPool") + else if (tf_node->op == "MaxPool") { param->pool_method = 0; } @@ -2053,7 +2046,7 @@ int load_conv(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* TFNode* input0 = tf_node->inputs[0]; /* input */ TFNode* input1 = tf_node->inputs[1]; /* weight */ TFNode* input2 = nullptr; - if(tf_node->inputs.size() > 2) + if (tf_node->inputs.size() > 2) { input2 = tf_node->inputs[2]; } @@ -2061,21 +2054,21 @@ int load_conv(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* struct conv_param* param = (struct conv_param*)node->op.param_mem; tensorflow::AttrValue value; - if(GetAttrValue(node_def, "dilations", value)) + if (GetAttrValue(node_def, "dilations", value)) { param->dilation_h = value.list().i(1); param->dilation_w = value.list().i(2); } - if(GetAttrValue(node_def, "padding", value)) + if (GetAttrValue(node_def, "padding", value)) { - if(value.s() == "VALID") + if (value.s() == "VALID") { param->pad_h0 = 0; param->pad_h1 = 0; param->pad_w0 = 0; param->pad_w1 = 0; } - else if(value.s() == "SAME") + else if (value.s() == "SAME") { param->pad_h0 = -1; param->pad_h1 = -1; @@ -2084,7 +2077,7 @@ int load_conv(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* } } - if(GetAttrValue(node_def, "strides", value)) + if (GetAttrValue(node_def, "strides", value)) { param->stride_h = value.list().i(1); param->stride_w = value.list().i(2); @@ -2096,18 +2089,18 @@ int load_conv(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* const tensorflow::NodeDef* weight_def = input1->pb_defs[0]; - if(GetAttrValue(weight_def, "value", value)) + if (GetAttrValue(weight_def, "value", value)) { const tensorflow::TensorShapeProto& shape = value.tensor().tensor_shape(); - if(shape.dim_size() == 4) + if (shape.dim_size() == 4) { kernel_h = shape.dim(0).size(); kernel_w = shape.dim(1).size(); in_channel = shape.dim(2).size(); out_channel = shape.dim(3).size(); } - else if(shape.dim_size() == 3) + else if (shape.dim_size() == 3) { kernel_h = 1; kernel_w = shape.dim(0).size(); @@ -2118,31 +2111,31 @@ int load_conv(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* ir_tensor_t* weight_tensor = input1->ir_tensor; int elem_size = out_channel * in_channel * kernel_h * kernel_w; - float* new_weight = ( float* )malloc(sizeof(float) * elem_size); + float* new_weight = (float*)malloc(sizeof(float) * elem_size); float* src = (float*)weight_tensor->data; - weight_tensor->data = sys_malloc(elem_size*sizeof(float)); + weight_tensor->data = sys_malloc(elem_size * sizeof(float)); float* ptr = (float*)weight_tensor->data; - for(int o = 0; o < out_channel; o++) - for(int h = 0; h < kernel_h; h++) - for(int w = 0; w < kernel_w; w++) - for(int i = 0; i < in_channel; i++) + for (int o = 0; o < out_channel; o++) + for (int h = 0; h < kernel_h; h++) + for (int w = 0; w < kernel_w; w++) + for (int i = 0; i < in_channel; i++) { - ptr[o*in_channel*kernel_h*kernel_w + i*kernel_h*kernel_w + h*kernel_w + w] - = src[h * (kernel_w * in_channel * out_channel) + w * (in_channel * out_channel) + i * out_channel + o]; + ptr[o * in_channel * kernel_h * kernel_w + i * kernel_h * kernel_w + h * kernel_w + w] + = src[h * (kernel_w * in_channel * out_channel) + w * (in_channel * out_channel) + i * out_channel + o]; } free(src); weight_tensor->tensor_type = TENSOR_TYPE_CONST; - if(tf_node->op == "DepthwiseConv2dNative") + if (tf_node->op == "DepthwiseConv2dNative") { group = in_channel; out_channel = in_channel * out_channel; in_channel = 1; } - int* dims = (int*)malloc(sizeof(int)*4); + int* dims = (int*)malloc(sizeof(int) * 4); dims[0] = out_channel; dims[1] = in_channel; dims[2] = kernel_h; @@ -2157,7 +2150,7 @@ int load_conv(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* auto saved_param = param; - if(tf_node->op == "DepthwiseConv2dNative") + if (tf_node->op == "DepthwiseConv2dNative") { in_channel = group; out_channel = out_channel / in_channel; @@ -2165,28 +2158,27 @@ int load_conv(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* int pb_def_num = tf_node->pb_defs.size(); - if(pb_def_num > 1) + if (pb_def_num > 1) { // the last one, const tensorflow::NodeDef* node_def = tf_node->pb_defs[pb_def_num - 1]; /* possible pad */ - if(node_def->op() == "Const") + if (node_def->op() == "Const") { tensorflow::AttrValue value; - if(GetAttrValue(node_def, "value", value) && value.has_tensor()) + if (GetAttrValue(node_def, "value", value) && value.has_tensor()) { const tensorflow::TensorProto& tf_tensor = value.tensor(); int dim_size = tf_tensor.tensor_shape().dim_size(); - if(dim_size == 2 && tf_tensor.tensor_shape().dim(0).size() == 4 && - tf_tensor.tensor_shape().dim(1).size() == 2) + if (dim_size == 2 && tf_tensor.tensor_shape().dim(0).size() == 4 && tf_tensor.tensor_shape().dim(1).size() == 2) { std::vector shape_data(8); - if(tf_tensor.tensor_content().size()) + if (tf_tensor.tensor_content().size()) { int* ptr = shape_data.data(); memcpy(ptr, tf_tensor.tensor_content().c_str(), tf_tensor.tensor_content().size()); @@ -2195,7 +2187,7 @@ int load_conv(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* { int data_num = tf_tensor.int_val_size(); - for(int i = 0; i < data_num; i++) + for (int i = 0; i < data_num; i++) { shape_data[i] = tf_tensor.int_val(i); } @@ -2220,7 +2212,7 @@ int load_batchnorm(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_nod const tensorflow::NodeDef* node_def = tf_node->pb_defs[0]; tensorflow::AttrValue value; - if(GetAttrValue(node_def, "epsilon", value)) + if (GetAttrValue(node_def, "epsilon", value)) { param->eps = value.f(); } @@ -2236,7 +2228,7 @@ int load_softmax(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_ struct softmax_param* param = (struct softmax_param*)node->op.param_mem; const tensorflow::NodeDef* node_def = tf_node->pb_defs[0]; tensorflow::AttrValue value; - if(GetAttrValue(node_def, "value", value)) + if (GetAttrValue(node_def, "value", value)) { const tensorflow::TensorProto& tf_tensor = value.tensor(); int axis = tf_tensor.int_val(0); @@ -2244,7 +2236,7 @@ int load_softmax(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_ } else param->axis = 1; - + return 0; } int load_relu(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* node) @@ -2256,43 +2248,41 @@ int load_relu(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* } static EltType MapEltwise(TFNode* tf_node, const std::string& elt_op) { - if(elt_op == "Add" || elt_op == "AddN") + if (elt_op == "Add" || elt_op == "AddN") return ELT_SUM; - else if(elt_op == "Mul") + else if (elt_op == "Mul") return ELT_PROD; - else if(elt_op == "Sub") + else if (elt_op == "Sub") return ELT_SUB; - else if(elt_op == "Rsqrt") + else if (elt_op == "Rsqrt") return ELT_RSQRT; - else if(elt_op == "Minimum") + else if (elt_op == "Minimum") return ELT_MIN_SCALAR; - else if(elt_op == "Exp") + else if (elt_op == "Exp") return ELT_EXP; - else if(elt_op == "Log") + else if (elt_op == "Log") return ELT_LOG; - else if(elt_op == "Pow") + else if (elt_op == "Pow") return ELT_POW; - else if(elt_op == "RealDiv") + else if (elt_op == "RealDiv") return ELT_DIV; - else if(elt_op == "Sqrt") + else if (elt_op == "Sqrt") return ELT_SQRT; - else if(elt_op == "Floor") + else if (elt_op == "Floor") return ELT_FLOOR; else return ELT_LAST; } int load_eltwise(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* node) { - if(tf_node->op == "Add" || tf_node->op == "Mul" || tf_node->op == "Sub" || tf_node->op == "Minimum" || - tf_node->op == "AddN" || tf_node->op == "Pow" || tf_node->op == "RealDiv") + if (tf_node->op == "Add" || tf_node->op == "Mul" || tf_node->op == "Sub" || tf_node->op == "Minimum" || tf_node->op == "AddN" || tf_node->op == "Pow" || tf_node->op == "RealDiv") { - if(tf_node->inputs.size() != 2) + if (tf_node->inputs.size() != 2) return false; } - else if(tf_node->op == "Rsqrt" || tf_node->op == "Exp" || tf_node->op == "Log" || tf_node->op == "Sqrt" || - tf_node->op == "Floor") + else if (tf_node->op == "Rsqrt" || tf_node->op == "Exp" || tf_node->op == "Log" || tf_node->op == "Sqrt" || tf_node->op == "Floor") { - if(tf_node->inputs.size() != 1) + if (tf_node->inputs.size() != 1) return false; } else @@ -2311,7 +2301,7 @@ static void* LoadConstParam(TFNode* tf_node) const tensorflow::NodeDef* node_def = tf_node->pb_defs[0]; - if(GetAttrValue(node_def, "value", value)) + if (GetAttrValue(node_def, "value", value)) { const tensorflow::TensorProto& tf_tensor = value.tensor(); void* mem_ptr = nullptr; @@ -2332,47 +2322,47 @@ int load_reduction(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_nod tensorflow::AttrValue value; GetAttrValue(node_def, "keep_dims", value); param->keepdim = value.b(); - if(tf_node->op == "Sum") + if (tf_node->op == "Sum") { param->type = 0; } - else if(tf_node->op == "Mean") + else if (tf_node->op == "Mean") { param->type = 1; } - else if(tf_node->op == "Asum") + else if (tf_node->op == "Asum") { param->type = 2; } - else if(tf_node->op == "Sqsum") + else if (tf_node->op == "Sqsum") { param->type = 3; } - else if(tf_node->op == "Max") + else if (tf_node->op == "Max") { param->type = 4; - } - else if(tf_node->op == "Min") + } + else if (tf_node->op == "Min") { param->type = 5; - } - else if(tf_node->op == "Prod") + } + else if (tf_node->op == "Prod") { param->type = 6; - } - else if(tf_node->op == "L2") + } + else if (tf_node->op == "L2") { param->type = 7; - } - else if(tf_node->op == "Logsum") + } + else if (tf_node->op == "Logsum") { param->type = 8; - } - else if(tf_node->op == "Logsumexp") + } + else if (tf_node->op == "Logsumexp") { param->type = 9; - } - int* data = (int*)LoadConstParam(input1); + } + int* data = (int*)LoadConstParam(input1); return 0; } int load_pad(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* node) @@ -2380,7 +2370,7 @@ int load_pad(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* n struct pad_param* param = (struct pad_param*)node->op.param_mem; TFNode* input = tf_node->inputs[1]; - int* paddings = ( int* )LoadConstParam(input); + int* paddings = (int*)LoadConstParam(input); param->mode = 0; param->pad_0_h = paddings[0]; param->pad_0_w = paddings[1]; @@ -2394,25 +2384,25 @@ int load_pad(TFNode* tf_node, TFGraph& tf_graph, ir_graph_t* graph, ir_node_t* n } void tensorflow_serializer::register_op_load() { - op_load_map["AvgPool"] = std::pair(OP_POOL, load_pool); - op_load_map["MaxPool"] = std::pair(OP_POOL, load_pool); - op_load_map["Conv2D"] = std::pair(OP_CONV, load_conv); - op_load_map["DepthwiseConv2dNative"] = std::pair(OP_CONV, load_conv); - op_load_map["FusedBatchNorm"] = std::pair(OP_BATCHNORM, load_batchnorm); - op_load_map["Relu6"] = std::pair(OP_RELU6, load_relu6); - op_load_map["Relu"] = std::pair(OP_RELU, load_relu); - op_load_map["Softmax"] = std::pair(OP_SOFTMAX, load_softmax); - op_load_map["Add"] = std::pair(OP_ELTWISE, load_eltwise); - op_load_map["Sub"] = std::pair(OP_ELTWISE, load_eltwise); - op_load_map["Mul"] = std::pair(OP_ELTWISE, load_eltwise); - op_load_map["Minimum"] = std::pair(OP_ELTWISE, load_eltwise); - op_load_map["Rsqrt"] = std::pair(OP_ELTWISE, load_eltwise); - op_load_map["Exp"] = std::pair(OP_ELTWISE, load_eltwise); - op_load_map["Log"] = std::pair(OP_ELTWISE, load_eltwise); - op_load_map["Pow"] = std::pair(OP_ELTWISE, load_eltwise); - op_load_map["RealDiv"] = std::pair(OP_ELTWISE, load_eltwise); - op_load_map["Sqrt"] = std::pair(OP_ELTWISE, load_eltwise); - op_load_map["AddN"] = std::pair(OP_ELTWISE, load_eltwise); - op_load_map["Mean"] = std::pair(OP_REDUCTION, load_reduction); - op_load_map["Pad"] = std::pair(OP_PAD, load_pad); + op_load_map["AvgPool"] = std::pair(OP_POOL, load_pool); + op_load_map["MaxPool"] = std::pair(OP_POOL, load_pool); + op_load_map["Conv2D"] = std::pair(OP_CONV, load_conv); + op_load_map["DepthwiseConv2dNative"] = std::pair(OP_CONV, load_conv); + op_load_map["FusedBatchNorm"] = std::pair(OP_BATCHNORM, load_batchnorm); + op_load_map["Relu6"] = std::pair(OP_RELU6, load_relu6); + op_load_map["Relu"] = std::pair(OP_RELU, load_relu); + op_load_map["Softmax"] = std::pair(OP_SOFTMAX, load_softmax); + op_load_map["Add"] = std::pair(OP_ELTWISE, load_eltwise); + op_load_map["Sub"] = std::pair(OP_ELTWISE, load_eltwise); + op_load_map["Mul"] = std::pair(OP_ELTWISE, load_eltwise); + op_load_map["Minimum"] = std::pair(OP_ELTWISE, load_eltwise); + op_load_map["Rsqrt"] = std::pair(OP_ELTWISE, load_eltwise); + op_load_map["Exp"] = std::pair(OP_ELTWISE, load_eltwise); + op_load_map["Log"] = std::pair(OP_ELTWISE, load_eltwise); + op_load_map["Pow"] = std::pair(OP_ELTWISE, load_eltwise); + op_load_map["RealDiv"] = std::pair(OP_ELTWISE, load_eltwise); + op_load_map["Sqrt"] = std::pair(OP_ELTWISE, load_eltwise); + op_load_map["AddN"] = std::pair(OP_ELTWISE, load_eltwise); + op_load_map["Mean"] = std::pair(OP_REDUCTION, load_reduction); + op_load_map["Pad"] = std::pair(OP_PAD, load_pad); } \ No newline at end of file From bb81f217e4778fcff08a12283195722ee31f77ea Mon Sep 17 00:00:00 2001 From: bzhang5 Date: Fri, 20 Aug 2021 07:34:05 +0000 Subject: [PATCH 7/8] apply code-format changes --- tools/convert_tool/tensorflow/tf2tengine.hpp | 29 ++++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/tools/convert_tool/tensorflow/tf2tengine.hpp b/tools/convert_tool/tensorflow/tf2tengine.hpp index 00505fb74..00199738e 100644 --- a/tools/convert_tool/tensorflow/tf2tengine.hpp +++ b/tools/convert_tool/tensorflow/tf2tengine.hpp @@ -55,12 +55,10 @@ extern "C" { #include "save_graph/op_include.h" } - -#define TF_RNN_LSTM 0 -#define TF_RNN_GRU 1 +#define TF_RNN_LSTM 0 +#define TF_RNN_GRU 1 #define TF_RNN_BASIC_LSTM 2 -#define TF_RNN_BASIC_RNN 3 - +#define TF_RNN_BASIC_RNN 3 struct TFNode { @@ -80,7 +78,9 @@ struct TFNode no_static_node = false; } - virtual ~TFNode() {} + virtual ~TFNode() + { + } }; struct LSTMNode : public TFNode @@ -120,9 +120,9 @@ struct LSTMNode : public TFNode auto rnn_ir = rnn_graph.begin(); auto rnn_end = rnn_graph.end(); - while(rnn_ir != rnn_end) + while (rnn_ir != rnn_end) { - delete(*rnn_ir); + delete (*rnn_ir); rnn_ir++; } } @@ -153,9 +153,9 @@ struct RNNNode : public TFNode auto rnn_ir = rnn_graph.begin(); auto rnn_end = rnn_graph.end(); - while(rnn_ir != rnn_end) + while (rnn_ir != rnn_end) { - delete(*rnn_ir); + delete (*rnn_ir); rnn_ir++; } } @@ -195,9 +195,9 @@ struct GRUNode : public TFNode auto rnn_ir = rnn_graph.begin(); auto rnn_end = rnn_graph.end(); - while(rnn_ir != rnn_end) + while (rnn_ir != rnn_end) { - delete(*rnn_ir); + delete (*rnn_ir); rnn_ir++; } } @@ -209,12 +209,11 @@ struct TFGraph ~TFGraph() { - for(auto node : seq_nodes) + for (auto node : seq_nodes) delete node; } }; - class tensorflow_serializer { public: @@ -239,7 +238,7 @@ class tensorflow_serializer int FindRNNScope(std::string& rnn_scope); void ParseLSTMGraph(LSTMNode* lstm_node, std::set& rnn_graph); void StripRNNScope(std::string& rnn_scope, int rnn_type); - void MergeReluMinimum(); + void MergeReluMinimum(); int MergeChildNode(TFNode* base_node, TFNode* child_node); int MergeParentNode(TFNode* base_node, TFNode* child_node); int BNRecursiveInputMerge(TFNode* node); From 532a1f99ee9bd5fbf34ce3dfd3054ca10e871474 Mon Sep 17 00:00:00 2001 From: bzhang5 <58622517+bzhang5@users.noreply.github.com> Date: Fri, 20 Aug 2021 15:43:22 +0800 Subject: [PATCH 8/8] Update CMakeLists.txt --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5177cb4f5..5b0597475 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,15 +49,15 @@ IF (NOT CMAKE_BUILD_TYPE) ENDIF() # Module options -OPTION (TENGINE_BUILD_BENCHMARK "Build benchmark" OFF) -OPTION (TENGINE_BUILD_EXAMPLES "Build examples" OFF) +OPTION (TENGINE_BUILD_BENCHMARK "Build benchmark" ON) +OPTION (TENGINE_BUILD_EXAMPLES "Build examples" ON) OPTION (TENGINE_BUILD_DEMO "Build demos" OFF) OPTION (TENGINE_BUILD_TESTS "Build tests" OFF) OPTION (TENGINE_BUILD_CPP_API "Build C++ API" OFF) # Tools options # Tools -OPTION (TENGINE_BUILD_CONVERT_TOOL "Build convert tool" ON) +OPTION (TENGINE_BUILD_CONVERT_TOOL "Build convert tool" OFF) OPTION (TENGINE_BUILD_QUANT_TOOL "Build quantization tool" OFF) # Multithreading option