diff --git a/CMakeLists.txt b/CMakeLists.txt index ef1b831aa..822185312 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -248,7 +248,7 @@ if (NOT USE_PRE_BUILT_NGRAPH) ExternalProject_Add( ext_ngraph GIT_REPOSITORY https://github.com/NervanaSystems/ngraph - GIT_TAG v0.27.1-rc.1 + GIT_TAG v0.28.0-rc.0 CMAKE_ARGS -DNGRAPH_DISTRIBUTED_ENABLE=${NGRAPH_DISTRIBUTED_ENABLE} -DNGRAPH_INSTALL_PREFIX=${NGRAPH_ARTIFACTS_DIR} @@ -275,6 +275,9 @@ if (NOT USE_PRE_BUILT_NGRAPH) endif() set(NGRAPH_INSTALL_DIR ${NGRAPH_ARTIFACTS_DIR}) +if(NGRAPH_BRIDGE_STATIC_LIB_ENABLE) + add_definitions(-DNGRAPH_BRIDGE_STATIC_LIB_ENABLE) +endif() if(OS_VERSION STREQUAL "\"centos\"") set(LIB "lib64") diff --git a/README.md b/README.md index 21c6b72d4..4358048c7 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ Once TensorFlow's dependencies are installed, clone the `ngraph-bridge` repo: git clone https://github.com/tensorflow/ngraph-bridge.git cd ngraph-bridge - git checkout v0.22.0-rc1 + git checkout v0.22.0-rc2 Run the following Python script to build TensorFlow, nGraph, and the bridge. Use Python 3.5: diff --git a/bazel/BUILD b/bazel/BUILD index 034ff0dec..18eba5c9a 100644 --- a/bazel/BUILD +++ b/bazel/BUILD @@ -134,6 +134,7 @@ cc_library( "-Wno-strict-overflow", '-D NGRAPH_BRIDGE_STATIC_LIB_ENABLE', '-D NGRAPH_TF_USE_GRAPPLER_OPTIMIZER', + '-D NGRAPH_CPU_STATIC_LIB_ENABLE', "-I ngraph_bridge", "-I logging", "-I external/ngraph/src", diff --git a/bazel/WORKSPACE b/bazel/WORKSPACE index c3c8aa84e..541bb891e 100644 --- a/bazel/WORKSPACE +++ b/bazel/WORKSPACE @@ -55,11 +55,11 @@ tf_workspace(path_prefix = "", tf_repo_name = "org_tensorflow") http_archive( name = "ngraph", build_file = "//:bazel/ngraph.BUILD", - sha256 = "903991dfdb63304bc08bebab68e0fcb3e62690763b886c42178f363a0beb00f4", - strip_prefix = "ngraph-0.27.1-rc.1", + sha256 = "be59da1e04840b3980d3bcba7925b99ac2007e37e3952ef7c77caedba9734654", + strip_prefix = "ngraph-0.28.0-rc.0", urls = [ - "https://mirror.bazel.build/github.com/NervanaSystems/ngraph/archive/v0.27.1-rc.1.tar.gz", - "https://github.com/NervanaSystems/ngraph/archive/v0.27.1-rc.1.tar.gz" + "https://mirror.bazel.build/github.com/NervanaSystems/ngraph/archive/v0.28.0-rc.0.tar.gz", + "https://github.com/NervanaSystems/ngraph/archive/v0.28.0-rc.0.tar.gz" ], ) diff --git a/bazel/ngraph.BUILD b/bazel/ngraph.BUILD index 5ac313c8a..ddc6b081d 100644 --- a/bazel/ngraph.BUILD +++ b/bazel/ngraph.BUILD @@ -68,12 +68,13 @@ cc_library( "-fstack-protector-all", '-D SHARED_LIB_PREFIX=\\"lib\\"', '-D SHARED_LIB_SUFFIX=\\".so\\"', - '-D NGRAPH_VERSION=\\"v0.27.1-rc.1\\"', + '-D NGRAPH_VERSION=\\"v0.28.0-rc.0\\"', "-D NGRAPH_DEX_ONLY", '-D PROJECT_ROOT_DIR=\\"\\"', '-D NGRAPH_STATIC_LIB_ENABLE', '-D NGRAPH_DYNAMIC_COMPONENTS_ENABLE', '-D NGRAPH_ENABLE_CPU_CONV_AUTO', + '-D NGRAPH_USE_LEGACY_MKLDNN', "-march=native", "-mtune=native", "-Wall", @@ -111,9 +112,10 @@ cc_library( "-fstack-protector-all", '-D SHARED_LIB_PREFIX=\\"lib\\"', '-D SHARED_LIB_SUFFIX=\\".so\\"', - '-D NGRAPH_VERSION=\\"v0.27.1-rc.1\\"', + '-D NGRAPH_VERSION=\\"v0.28.0-rc.0\\"', "-D NGRAPH_DEX_ONLY", '-D PROJECT_ROOT_DIR=\\"\\"', + '-D NGRAPH_USE_LEGACY_MKLDNN', ] + CXX_ABI, linkopts = [ "-Wl,-z,noexecstack", @@ -166,6 +168,7 @@ cc_library( "src/ngraph/runtime/cpu/builder/convert.cpp", "src/ngraph/runtime/cpu/builder/convert_layout.cpp", "src/ngraph/runtime/cpu/builder/convolution.cpp", + "src/ngraph/runtime/cpu/builder/cum_sum.cpp", "src/ngraph/runtime/cpu/builder/dot.cpp", "src/ngraph/runtime/cpu/builder/dropout.cpp", "src/ngraph/runtime/cpu/builder/embedding_lookup.cpp", @@ -269,10 +272,11 @@ cc_library( "-fstack-protector-all", '-D SHARED_LIB_PREFIX=\\"lib\\"', '-D SHARED_LIB_SUFFIX=\\".so\\"', - '-D NGRAPH_VERSION=\\"v0.27.1-rc.1\\"', + '-D NGRAPH_VERSION=\\"v0.28.0-rc.0\\"', "-D NGRAPH_DEX_ONLY", '-D PROJECT_ROOT_DIR=\\"\\"', '-D NGRAPH_CPU_STATIC_LIB_ENABLE', + '-D NGRAPH_USE_LEGACY_MKLDNN=\\"TRUE\\"', "-march=native", "-mtune=native", "-Wall", diff --git a/build_ngtf.py b/build_ngtf.py index f6127829d..71f7f0220 100755 --- a/build_ngtf.py +++ b/build_ngtf.py @@ -53,7 +53,7 @@ def main(): ''' # Component versions - ngraph_version = "v0.27.1-rc.1" + ngraph_version = "v0.28.0-rc.0" tf_version = "v1.14.0" # Command line parser options @@ -412,6 +412,7 @@ def main(): if (arguments.use_ngraph_staticlibs): ngraph_tf_cmake_flags.extend(["-DNGRAPH_BRIDGE_STATIC_LIB_ENABLE=TRUE"]) + if (arguments.debug_build): ngraph_tf_cmake_flags.extend(["-DCMAKE_BUILD_TYPE=Debug"]) diff --git a/examples/cpp/hello_tf.cpp b/examples/cpp/hello_tf.cpp index e8097a30e..0a549f241 100644 --- a/examples/cpp/hello_tf.cpp +++ b/examples/cpp/hello_tf.cpp @@ -35,16 +35,20 @@ using namespace std; // Prints the available backends -void PrintAvailableBackends() { +int PrintAvailableBackends() { // Get the list of backends auto supported_backends = tensorflow::ngraph_bridge::BackendManager::GetSupportedBackendNames(); vector backends(supported_backends.begin(), supported_backends.end()); - - cout << "Available backends: " << endl; + if (backends.empty()) { + std::cout << "No backend available " << std::endl; + return -1; + } + std::cout << "Available backends: " << std::endl; for (auto& backend_name : backends) { - cout << "Backend: " << backend_name << std::endl; + std::cout << "Backend: " << backend_name << std::endl; } + return 0; } // Create a simple computation graph and run @@ -116,13 +120,18 @@ void PrintVersion() { ? std::string("Yes") : std::string("No")) << std::endl; - - PrintAvailableBackends(); + std::cout << std::endl; } int main(int argc, char** argv) { PrintVersion(); + // Print the avialable backends and if none are available + // error out + if (PrintAvailableBackends()) { + return -1; + } + // Run a simple example RunSimpleNetworkExample(); diff --git a/examples/cpp/inference/CMakeLists.txt b/examples/cpp/inference/CMakeLists.txt index 1ef7cb816..4688c7be7 100644 --- a/examples/cpp/inference/CMakeLists.txt +++ b/examples/cpp/inference/CMakeLists.txt @@ -61,6 +61,10 @@ if (APPLE) add_definitions(-DTEST_SINGLE_INSTANCE) endif() +if(NGRAPH_BRIDGE_STATIC_LIB_ENABLE) + add_definitions(-DNGRAPH_BRIDGE_STATIC_LIB_ENABLE) +endif() + if(NGRAPH_BRIDGE_STATIC_LIB_ENABLE) target_link_libraries(${APP_NAME} -Wl,--whole-archive diff --git a/examples/cpp/inference/infer_multiple_networks.cc b/examples/cpp/inference/infer_multiple_networks.cc index d5ea4b1bf..8dc68c227 100644 --- a/examples/cpp/inference/infer_multiple_networks.cc +++ b/examples/cpp/inference/infer_multiple_networks.cc @@ -164,6 +164,13 @@ int main(int argc, char** argv) { return -1; } +// Register cpu backend for static linking +// [TODO]: Revisit this to see if we can remove registering here and register +// only in BackendManager. +#if defined(NGRAPH_BRIDGE_STATIC_LIB_ENABLE) + ngraph_register_cpu_backend(); +#endif + const char* backend = "CPU"; if (SetNGraphBackend(backend) != tf::Status::OK()) { std::cout << "Error: Cannot set the backend: " << backend << std::endl; diff --git a/examples/cpp/inference/infer_single_network.cc b/examples/cpp/inference/infer_single_network.cc index 5627ecdf5..b689cf657 100644 --- a/examples/cpp/inference/infer_single_network.cc +++ b/examples/cpp/inference/infer_single_network.cc @@ -160,6 +160,11 @@ int main(int argc, char** argv) { return -1; } +// Register cpu backend for static linking +#if defined(NGRAPH_BRIDGE_STATIC_LIB_ENABLE) + ngraph_register_cpu_backend(); +#endif + const char* backend = "CPU"; if (SetNGraphBackend(backend) != tf::Status::OK()) { std::cout << "Error: Cannot set the backend: " << backend << std::endl; diff --git a/ngraph_bridge/CMakeLists.txt b/ngraph_bridge/CMakeLists.txt index eb104ae3b..9118f71c4 100644 --- a/ngraph_bridge/CMakeLists.txt +++ b/ngraph_bridge/CMakeLists.txt @@ -98,6 +98,18 @@ if(NGRAPH_TF_ENABLE_VARIABLES_AND_OPTIMIZERS) add_definitions(-DNGRAPH_TF_ENABLE_VARIABLES_AND_OPTIMIZERS) endif() +if(NGRAPH_BRIDGE_STATIC_LIB_ENABLE) + add_definitions(-DNGRAPH_BRIDGE_STATIC_LIB_ENABLE) +endif() + +if(NGRAPH_CPU_STATIC_LIB_ENABLE) + add_definitions(-DNGRAPH_CPU_STATIC_LIB_ENABLE) +endif() + +if(NGRAPH_INTERPRETER_STATIC_LIB_ENABLE) + add_definitions(-DNGRAPH_INTERPRETER_STATIC_LIB_ENABLE) +endif() + if(NGRAPH_TF_USE_GRAPPLER_OPTIMIZER) list(REMOVE_ITEM SRC ngraph_rewrite_pass.cc) diff --git a/ngraph_bridge/enable_variable_ops/ngraph_rewrite_pass.cc b/ngraph_bridge/enable_variable_ops/ngraph_rewrite_pass.cc index ea97ff417..bc5ead221 100644 --- a/ngraph_bridge/enable_variable_ops/ngraph_rewrite_pass.cc +++ b/ngraph_bridge/enable_variable_ops/ngraph_rewrite_pass.cc @@ -226,8 +226,12 @@ class NGraphEncapsulationPass : public NGraphRewritePass { // 4. Encapsulate clusters then, if requested, dump the graphs. FunctionDefLibrary* fdeflib_new = new FunctionDefLibrary(); - TF_RETURN_IF_ERROR(EncapsulateClusters(options.graph->get(), idx, - fdeflib_new, config_map, {0, {}})); + auto status = EncapsulateClusters(options.graph->get(), idx, fdeflib_new, + config_map, {0, {}}); + if (status != Status::OK()) { + delete (fdeflib_new); + return status; + } // TODO: not using fdeflib_new in this path. Only grappler path uses it free(fdeflib_new); if (DumpEncapsulatedGraphs()) { diff --git a/ngraph_bridge/grappler/ngraph_optimizer.cc b/ngraph_bridge/grappler/ngraph_optimizer.cc index 279388bc1..a9551d1b6 100644 --- a/ngraph_bridge/grappler/ngraph_optimizer.cc +++ b/ngraph_bridge/grappler/ngraph_optimizer.cc @@ -260,9 +260,13 @@ Status NgraphOptimizer::Optimize(tensorflow::grappler::Cluster* cluster, // 4. Encapsulate clusters then, if requested, dump the graphs. FunctionDefLibrary* fdeflib_new = new FunctionDefLibrary(); - TF_RETURN_IF_ERROR( - // TODO: right now _ngraph_aot_requested is passed along in config_map. - EncapsulateClusters(&graph, idx, fdeflib_new, config_map, aot_info)); + // TODO: right now _ngraph_aot_requested is passed along in config_map. + auto status = + EncapsulateClusters(&graph, idx, fdeflib_new, config_map, aot_info); + if (status != Status::OK()) { + delete (fdeflib_new); + return status; + } if (DumpEncapsulatedGraphs()) { DumpGraphs(graph, idx, "encapsulated", "Graph with Clusters Encapsulated"); } diff --git a/ngraph_bridge/ngraph_assign_clusters.cc b/ngraph_bridge/ngraph_assign_clusters.cc index 279a7a1c3..5cd9bd4e7 100644 --- a/ngraph_bridge/ngraph_assign_clusters.cc +++ b/ngraph_bridge/ngraph_assign_clusters.cc @@ -817,6 +817,10 @@ Status GetNodeCluster(const Node* node, int* cluster) { return s; } +void ResetAssignClusters(Graph* graph) { + ClearAttribute(graph, {"_ngraph_cluster"}); +} + } // namespace ngraph_bridge } // namespace tensorflow diff --git a/ngraph_bridge/ngraph_assign_clusters.h b/ngraph_bridge/ngraph_assign_clusters.h index 33854aa65..1fbba02df 100644 --- a/ngraph_bridge/ngraph_assign_clusters.h +++ b/ngraph_bridge/ngraph_assign_clusters.h @@ -25,6 +25,8 @@ namespace tensorflow { namespace ngraph_bridge { Status AssignClusters(Graph* graph); +// reset the effect of AssignClusters +void ResetAssignClusters(Graph* graph); Status GetNodeCluster(const Node* node, int* cluster); } // namespace ngraph_bridge diff --git a/ngraph_bridge/ngraph_backend_manager.cc b/ngraph_bridge/ngraph_backend_manager.cc index 5e02ad4cd..926437200 100644 --- a/ngraph_bridge/ngraph_backend_manager.cc +++ b/ngraph_bridge/ngraph_backend_manager.cc @@ -45,6 +45,14 @@ Status BackendManager::SetBackendName(const string& backend_name) { } Status BackendManager::CreateBackend(const string& backend_name) { +// Register backends for static linking +#if defined(NGRAPH_CPU_STATIC_LIB_ENABLE) + ngraph_register_cpu_backend(); +#endif +#if defined(NGRAPH_INTERPRETER_STATIC_LIB_ENABLE) + ngraph_register_interpreter_backend(); +#endif + std::lock_guard lock(BackendManager::ng_backend_map_mutex_); auto itr = BackendManager::ng_backend_map_.find(backend_name); // if backend does not exist create it @@ -126,10 +134,24 @@ void BackendManager::UnlockBackend(const string& backend_name) { // Returns the nGraph supported backend names vector BackendManager::GetSupportedBackendNames() { +// Register backends for static linking +#if defined(NGRAPH_CPU_STATIC_LIB_ENABLE) + ngraph_register_cpu_backend(); +#endif +#if defined(NGRAPH_INTERPRETER_STATIC_LIB_ENABLE) + ngraph_register_interpreter_backend(); +#endif return ng::runtime::BackendManager::get_registered_backends(); } size_t BackendManager::GetNumOfSupportedBackends() { +// Register backends for static linking +#if defined(NGRAPH_CPU_STATIC_LIB_ENABLE) + ngraph_register_cpu_backend(); +#endif +#if defined(NGRAPH_INTERPRETER_STATIC_LIB_ENABLE) + ngraph_register_interpreter_backend(); +#endif return ng::runtime::BackendManager::get_registered_backends().size(); } diff --git a/ngraph_bridge/ngraph_builder.cc b/ngraph_bridge/ngraph_builder.cc index 89b3271e3..0d7ee3eb6 100644 --- a/ngraph_bridge/ngraph_builder.cc +++ b/ngraph_bridge/ngraph_builder.cc @@ -27,6 +27,7 @@ #include "ngraph/builder/quantize_builder.hpp" #include "ngraph/op/argmax.hpp" #include "ngraph/op/argmin.hpp" +#include "ngraph/op/experimental/layers/interpolate.hpp" #include "ngraph/op/util/logical_reduction.hpp" #include "ngraph/slice_plan.hpp" @@ -785,23 +786,26 @@ static Status TranslateBatchMatMulOp( if (ng_lhs_shape.size() != ng_rhs_shape.size()) { return errors::InvalidArgument( - "Dimensions of two input args are not the same for BatchMatMul"); + "Dimensions of two input args are not the same for BatchMatMul. Left " + "shape is ", + ng::join(ng_lhs_shape), " of rank ", ng_lhs_shape.size(), + " and Right shape is ", ng::join(ng_rhs_shape), " of rank ", + ng_rhs_shape.size()); } size_t n_dims = ng_lhs_shape.size(); if (n_dims < 2) { return errors::InvalidArgument( - "Dimensions of input args for BatchMatMul must be >=2", n_dims); + "Dimensions of input args for BatchMatMul must be >=2 but is ", n_dims); } - ng::AxisVector out_axes; for (size_t i = 0; i < n_dims - 2; ++i) { if (ng_lhs_shape[i] != ng_rhs_shape[i]) { return errors::InvalidArgument( "ng_lhs_shape and ng_rhs_shape must be the same for BatchMatMul " - "for each dimension", - i); + "for each dimension but found ", + i, "th dimension different. Left shape is ", ng::join(ng_lhs_shape), + "and Right shape is ", ng::join(ng_rhs_shape)); } - out_axes.push_back(i); } bool tf_adj_x = false; @@ -809,146 +813,54 @@ static Status TranslateBatchMatMulOp( TF_RETURN_IF_ERROR(GetNodeAttr(op->attrs(), "adj_x", &tf_adj_x)); TF_RETURN_IF_ERROR(GetNodeAttr(op->attrs(), "adj_y", &tf_adj_y)); - auto ng_lhs_axes = out_axes; - auto ng_rhs_axes = out_axes; - - // Get the backend name, if the backend is CPU and n_dims >= 3 - // then use the BatchMatMul op supported by nGraph - if (n_dims >= 3 && backend_name == "CPU") { + if (n_dims == 2) { // Transpose X if AdjX = true if (tf_adj_x) { - ng_lhs_axes.push_back(n_dims - 1); - ng_lhs_axes.push_back(n_dims - 2); - ng_lhs = ng::builder::numpy_transpose(ng_lhs, ng_lhs_axes); + ng_lhs = ng::builder::numpy_transpose(ng_lhs, {1, 0}); Builder::SetTracingInfo(op->name(), ng_lhs); - ng_lhs_shape = ng_lhs->get_shape(); - } else { - ng_lhs_axes.push_back(n_dims - 2); - ng_lhs_axes.push_back(n_dims - 1); } // Transpose Y if AdjY = true if (tf_adj_y) { - ng_rhs_axes.push_back(n_dims - 1); - ng_rhs_axes.push_back(n_dims - 2); - ng_rhs = ng::builder::numpy_transpose(ng_rhs, ng_rhs_axes); + ng_rhs = ng::builder::numpy_transpose(ng_rhs, {1, 0}); Builder::SetTracingInfo(op->name(), ng_rhs); - ng_rhs_shape = ng_rhs->get_shape(); - } else { - ng_rhs_axes.push_back(n_dims - 2); - ng_rhs_axes.push_back(n_dims - 1); - } - - if (n_dims == 3) { - SaveNgOp(ng_op_map, op->name(), ConstructNgNode( - op->name(), ng_lhs, ng_rhs)); - } else { - // Find the compound size for dim1 so as to reshape to 3D - size_t compound_size = 1; - for (size_t i = 0; i < out_axes.size(); i++) { - compound_size *= ng_lhs_shape[i]; - } - - ng::Shape tmp_lhs_shape = {compound_size, ng_lhs_shape[n_dims - 2], - ng_lhs_shape[n_dims - 1]}; - ng::Shape tmp_rhs_shape = {compound_size, ng_rhs_shape[n_dims - 2], - ng_rhs_shape[n_dims - 1]}; - - auto output_shape = ng_lhs_shape; - output_shape[n_dims - 1] = ng_rhs_shape[n_dims - 1]; - ng::AxisVector tmp_axes = {0, 1, 2}; - - std::shared_ptr lhs_reshape = - ConstructNgNode(op->name(), ng_lhs, ng_lhs_axes, - tmp_lhs_shape); - std::shared_ptr rhs_reshape = - ConstructNgNode(op->name(), ng_rhs, ng_rhs_axes, - tmp_rhs_shape); - std::shared_ptr batchmatmul = - ConstructNgNode(op->name(), lhs_reshape, - rhs_reshape); - SaveNgOp(ng_op_map, op->name(), - ConstructNgNode(op->name(), batchmatmul, - tmp_axes, output_shape)); } + SaveNgOp(ng_op_map, op->name(), + ConstructNgNode(op->name(), ng_lhs, ng_rhs)); + } else if (n_dims == 3) { + SaveNgOp(ng_op_map, op->name(), + ConstructNgNode( + op->name(), ng_lhs, ng_rhs, tf_adj_x, tf_adj_y)); } else { - if (tf_adj_x) { - ng_lhs_axes.push_back(n_dims - 1); - ng_lhs_axes.push_back(n_dims - 2); - ng_lhs = ng::builder::numpy_transpose(ng_lhs, ng_lhs_axes); - Builder::SetTracingInfo(op->name(), ng_lhs); - } - if (tf_adj_y) { - ng_rhs_axes.insert(ng_rhs_axes.begin(), n_dims - 2); - ng_rhs_axes.insert(ng_rhs_axes.begin(), n_dims - 1); - ng_rhs = ng::builder::numpy_transpose(ng_rhs, ng_rhs_axes); - Builder::SetTracingInfo(op->name(), ng_rhs); - } else { - ng_rhs_axes.insert(ng_rhs_axes.begin(), n_dims - 1); - ng_rhs_axes.insert(ng_rhs_axes.begin(), n_dims - 2); - ng_rhs = ng::builder::numpy_transpose(ng_rhs, ng_rhs_axes); - Builder::SetTracingInfo(op->name(), ng_rhs); - } + ng::AxisVector out_axes(n_dims); + std::iota(out_axes.begin(), out_axes.end(), 0); - ng_lhs_shape = ng_lhs->get_shape(); - ng_rhs_shape = ng_rhs->get_shape(); - - if (ng_lhs_shape[n_dims - 1] != ng_rhs_shape[0]) { - return errors::InvalidArgument( - "The last dimension of ng_lhs and the first dimension of ng_rhs " - "should have the same size"); + size_t compound_size = 1; + for (size_t i = 0; i < n_dims - 2; i++) { + compound_size *= ng_lhs_shape[i]; } - if (n_dims == 2) { - SaveNgOp(ng_op_map, op->name(), - ConstructNgNode(op->name(), ng_lhs, ng_rhs)); - } else { - auto output_shape = ng_lhs_shape; - output_shape[n_dims - 1] = ng_rhs_shape[1]; - auto dot_output = - ConstructNgNode(op->name(), ng_lhs, ng_rhs); - - size_t compound_size = 1; - for (size_t i = 0; i < out_axes.size(); i++) { - compound_size *= output_shape[i]; - } - auto dot_axes = out_axes; - dot_axes.push_back(n_dims - 2); - dot_axes.push_back(n_dims - 1); - for (size_t i = 0; i < out_axes.size(); i++) { - dot_axes.push_back(n_dims + i); - } - ng::Shape dot_shape = {compound_size, ng_lhs_shape[n_dims - 2], - ng_rhs_shape[1], compound_size}; - std::shared_ptr dot_reshape; - if (n_dims == 3) { - dot_reshape = dot_output; - } else { - dot_reshape = ConstructNgNode( - op->name(), dot_output, dot_axes, dot_shape); - } - ng::Shape tmp_shape = {1, ng_lhs_shape[n_dims - 2], ng_rhs_shape[1]}; - vector> tmp_tensors; - for (size_t i = 0; i < dot_shape[0]; i++) { - const std::vector lower_bound{i, 0, 0, i}; - const std::vector upper_bound{i + 1, dot_shape[1], dot_shape[2], - i + 1}; - auto slice_out = ConstructNgNode( - op->name(), dot_reshape, lower_bound, upper_bound); - auto reshape_out = ConstructNgNode( - op->name(), slice_out, ng::AxisVector{0, 1, 2, 3}, tmp_shape); - tmp_tensors.push_back(reshape_out); - } - auto concat_op = - ConstructNgNode(op->name(), tmp_tensors, 0); - if (n_dims == 3) { - SaveNgOp(ng_op_map, op->name(), concat_op); - } else { - SaveNgOp( - ng_op_map, op->name(), - ConstructNgNode( - op->name(), concat_op, ng::AxisVector{0, 1, 2}, output_shape)); - } - } + ng::Shape tmp_lhs_shape = {compound_size, ng_lhs_shape[n_dims - 2], + ng_lhs_shape[n_dims - 1]}; + ng::Shape tmp_rhs_shape = {compound_size, ng_rhs_shape[n_dims - 2], + ng_rhs_shape[n_dims - 1]}; + + auto output_shape = ng_lhs_shape; + output_shape[n_dims - 2] = ng_lhs_shape[n_dims - (tf_adj_x ? 1 : 2)]; + output_shape[n_dims - 1] = ng_rhs_shape[n_dims - (tf_adj_y ? 2 : 1)]; + ng::AxisVector tmp_axes = {0, 1, 2}; + + std::shared_ptr lhs_reshape = + ConstructNgNode(op->name(), ng_lhs, out_axes, + tmp_lhs_shape); + std::shared_ptr rhs_reshape = + ConstructNgNode(op->name(), ng_rhs, out_axes, + tmp_rhs_shape); + std::shared_ptr batchmatmul_transpose = + ConstructNgNode( + op->name(), lhs_reshape, rhs_reshape, tf_adj_x, tf_adj_y); + SaveNgOp(ng_op_map, op->name(), + ConstructNgNode( + op->name(), batchmatmul_transpose, tmp_axes, output_shape)); } return Status::OK(); } @@ -965,7 +877,11 @@ static Status TranslateBatchMatMulV2Op( if (ng_lhs_shape.size() != ng_rhs_shape.size()) { return errors::InvalidArgument( - "Dimensions of two input args are not the same for BatchMatMul"); + "Dimensions of two input args are not the same for BatchMatMul. Left " + "shape is ", + ng::join(ng_lhs_shape), " of rank ", ng_lhs_shape.size(), + " and Right shape is ", ng::join(ng_rhs_shape), " of rank ", + ng_rhs_shape.size()); } for (size_t i = 0; i < n_dims - 2; ++i) { @@ -977,10 +893,10 @@ static Status TranslateBatchMatMulV2Op( "for each dimension. Failed to match dimension ", i, " where lhs was ", ng_lhs_shape[i], " and rhs was ", ng_rhs_shape[i]); - } else if ((ng_lhs_shape[i] == 1) || (ng_rhs_shape[i] == 1)) { + } else if (ng_lhs_shape[i] != ng_lhs_shape[i]) { return errors::Unimplemented( "ng_lhs_shape and ng_rhs_shape must be the same for each dimension, " - "for current implementation of BatchMatMulV2." + "for current implementation of BatchMatMulV2. " "Failed to match dimension ", i, " where lhs was ", ng_lhs_shape[i], " and rhs was ", ng_rhs_shape[i]); @@ -1630,6 +1546,56 @@ static Status TranslateConv3DOp(const Node* op, return Status::OK(); } +// Translate TranslateCropAndResizeOp op +static Status TranslateCropAndResizeOp(const Node* op, + const std::vector&, + Builder::OpMap& ng_op_map) { + shared_ptr image, boxes, box_ind, crop_size; + TF_RETURN_IF_ERROR( + GetInputNodes(ng_op_map, op, &image, &boxes, &box_ind, &crop_size)); + + // Get the attributes + float extrapolation_value; + std::string method; + TF_RETURN_IF_ERROR( + GetNodeAttr(op->attrs(), "extrapolation_value", &extrapolation_value)); + TF_RETURN_IF_ERROR(GetNodeAttr(op->attrs(), "method", &method)); + + ng::op::CropAndResize::ResizeMethod ng_method = + ng::op::CropAndResize::ResizeMethod::unspecified; + if (method == "bilinear") { + ng_method = ng::op::CropAndResize::ResizeMethod::bilinear; + } else if (method == "nearest") { + ng_method = ng::op::CropAndResize::ResizeMethod::nearest; + } else { + return errors::Internal( + "Expected crop and resize's interpolation mode to be bilinear or " + "nearest, but got ", + extrapolation_value, " in op ", op->name()); + } + + SaveNgOp(ng_op_map, op->name(), + ConstructNgNode(op->name(), image, boxes, + box_ind, crop_size, ng_method, + extrapolation_value)); + return Status::OK(); +} + +static Status TranslateCumsumOp(const Node* op, + const std::vector&, + Builder::OpMap& ng_op_map) { + shared_ptr ng_x, ng_axis; + TF_RETURN_IF_ERROR(GetInputNodes(ng_op_map, op, &ng_x, &ng_axis)); + bool exclusive, reverse; + TF_RETURN_IF_ERROR(GetNodeAttr(op->attrs(), "exclusive", &exclusive)); + TF_RETURN_IF_ERROR(GetNodeAttr(op->attrs(), "reverse", &reverse)); + + SaveNgOp(ng_op_map, op->name(), + ConstructNgNode(op->name(), ng_x, ng_axis, exclusive, + reverse)); + return Status::OK(); +} + // Translate DepthToSpace op static Status TranslateDepthToSpaceOp(const Node* op, const std::vector&, @@ -3357,8 +3323,17 @@ static Status TranslateQuantizeAndDequantizeV2Op( op->name(), ng_r_et, ng::Shape(), std::vector({scale})); auto ng_offset = ConstructNgNode( op->name(), ng_q_et, ng::Shape(), std::vector({0})); - ng::op::Quantize::RoundMode ng_round_mode = - ng::op::Quantize::RoundMode::ROUND_NEAREST_TOWARD_INFINITY; + ng::op::Quantize::RoundMode ng_round_mode; + string round_mode_string; + TF_RETURN_IF_ERROR( + GetNodeAttr(op->attrs(), "round_mode", &round_mode_string)); + if (round_mode_string == "HALF_UP") { + ng_round_mode = ng::op::Quantize::RoundMode::ROUND_NEAREST_UPWARD; + } else if (round_mode_string == "HALF_TO_EVEN") { + ng_round_mode = ng::op::Quantize::RoundMode::ROUND_NEAREST_TOWARD_EVEN; + } else { + return errors::Internal("Tensorflow Rounding Mode not supported by Ngraph"); + } auto ng_quant = ConstructNgNode( op->name(), ng_input, ng_scale, ng_offset, ng_q_et, ng::AxisSet(), ng_round_mode); @@ -3638,10 +3613,17 @@ static Status TranslateQuantizeV2Op(const Node* op, ng::element::Type ng_et; TF_RETURN_IF_ERROR(TFDataTypeToNGraphElementType(dtype, &ng_et)); - // TODO: Only RoundMode = ROUND_NEAREST_TOWARD_EVEN is supported, for now. - // Support other modes later - ng::op::Quantize::RoundMode ng_round_mode = - ng::op::Quantize::RoundMode::ROUND_NEAREST_TOWARD_EVEN; + ng::op::Quantize::RoundMode ng_round_mode; + string round_mode_string; + TF_RETURN_IF_ERROR( + GetNodeAttr(op->attrs(), "round_mode", &round_mode_string)); + if (round_mode_string == "HALF_UP") { + ng_round_mode = ng::op::Quantize::RoundMode::ROUND_NEAREST_UPWARD; + } else if (round_mode_string == "HALF_TO_EVEN") { + ng_round_mode = ng::op::Quantize::RoundMode::ROUND_NEAREST_TOWARD_EVEN; + } else { + return errors::Internal("Tensorflow Rounding Mode not supported by Ngraph"); + } auto ng_node = ng::builder::QuantizeBuilder(ng_input, ng_min, ng_max, ng_et, ng::AxisSet(), ng_round_mode); @@ -3763,6 +3745,38 @@ static Status TranslateReshapeOp( return Status::OK(); } +static Status TranslateResizeBilinearOp( + const Node* op, const std::vector& static_input_map, + Builder::OpMap& ng_op_map) { + shared_ptr images; + TF_RETURN_IF_ERROR(GetInputNodes(ng_op_map, op, &images, nullptr)); + + std::vector size_vector; + TF_RETURN_IF_ERROR( + GetStaticInputVector(op, 1, static_input_map, &size_vector)); + + auto size_int64 = ConstructNgNode( + op->name(), ngraph::element::i64, ng::Shape{2}, size_vector); + + bool align_corners; + TF_RETURN_IF_ERROR(GetNodeAttr(op->attrs(), "align_corners", &align_corners)); + + ngraph::op::InterpolateAttrs attrs; + attrs.align_corners = align_corners; + attrs.mode = "linear"; + attrs.antialias = false; + // The TF "images" is has dimensions [batch, height, width, channels]. + // So 1 and 2 are the spatial axes + // TODO check this parameter + attrs.axes = {1, 2}; + // TODO: pads_begin and pads_end are not populated. Check correctness + + SaveNgOp(ng_op_map, op->name(), ConstructNgNode( + op->name(), images, size_int64, attrs)); + + return Status::OK(); +} + static Status TranslateRsqrtOp( const Node* op, const std::vector& static_input_map, Builder::OpMap& ng_op_map) { @@ -3781,6 +3795,34 @@ static Status TranslateRsqrtOp( }); } +static Status TranslateScatterNdOp( + const Node* op, const std::vector& static_input_map, + Builder::OpMap& ng_op_map) { + shared_ptr ng_indices; + shared_ptr ng_updates; + TF_RETURN_IF_ERROR( + GetInputNodes(ng_op_map, op, &ng_indices, &ng_updates, nullptr)); + + std::vector ng_shape; + TF_RETURN_IF_ERROR(GetStaticInputVector(op, 2, static_input_map, &ng_shape)); + // Copy the int vector to a size_t vector, because that is what ng::Shape + // accepts + std::vector ng_shape_size_t(ng_shape.begin(), ng_shape.end()); + + // Create a tensor and populate the tensor with "0" to Add to ScatterNd + auto et = ng_updates->get_element_type(); + std::vector constant_values(ng::shape_size(ng_shape_size_t), + "0"); + auto ng_inputs = ConstructNgNode( + op->name(), et, ng::Shape(ng_shape_size_t), constant_values); + + SaveNgOp(ng_op_map, op->name(), + ConstructNgNode(op->name(), ng_inputs, + ng_indices, ng_updates)); + + return Status::OK(); +} + static Status TranslateRsqrtGradOp(const Node* op, const std::vector&, Builder::OpMap& ng_op_map) { @@ -5005,6 +5047,7 @@ const static std::map< {"All", TranslateDirectReduceOp}, {"ArgMax", TranslateArgMinMaxOp}, {"ArgMin", TranslateArgMinMaxOp}, + {"Atan2", TranslateBinaryOp}, {"AvgPool", TranslateAvgPoolOp}, {"AvgPoolGrad", TranslateAvgPoolGradOp}, {"BatchMatMul", TranslateBatchMatMulOp}, {"BatchMatMulV2", TranslateBatchMatMulV2Op}, @@ -5016,7 +5059,8 @@ const static std::map< {"Conv2DBackpropFilter", TranslateConv2DBackpropFilterOp}, {"Conv2DBackpropInput", TranslateConv2DBackpropInputOp}, {"Conv3D", TranslateConv3DOp}, {"Cos", TranslateUnaryOp}, - {"DepthToSpace", TranslateDepthToSpaceOp}, + {"CropAndResize", TranslateCropAndResizeOp}, + {"Cumsum", TranslateCumsumOp}, {"DepthToSpace", TranslateDepthToSpaceOp}, {"DepthwiseConv2dNative", TranslateDepthwiseConv2dNativeOp}, {"Dequantize", TranslateDequantizeOp}, {"Equal", TranslateBinaryOp}, @@ -5085,9 +5129,11 @@ const static std::map< {"Reciprocal", TranslateReciprocalOp}, {"Relu", TranslateUnaryOp}, {"Relu6", TranslateRelu6Op}, {"ReluGrad", TranslateReluGradOp}, {"Reshape", TranslateReshapeOp}, + {"ResizeBilinear", TranslateResizeBilinearOp}, {"Rsqrt", TranslateRsqrtOp}, {"RsqrtGrad", TranslateRsqrtGradOp}, - {"Select", TranslateSelectOp}, {"Shape", TranslateShapeOp}, - {"Sigmoid", TranslateSigmoidOp}, {"SigmoidGrad", TranslateSigmoidGradOp}, + {"ScatterNd", TranslateScatterNdOp}, {"Select", TranslateSelectOp}, + {"Shape", TranslateShapeOp}, {"Sigmoid", TranslateSigmoidOp}, + {"SigmoidGrad", TranslateSigmoidGradOp}, {"Sin", TranslateUnaryOp}, {"Size", TranslateSizeOp}, {"Sign", TranslateUnaryOp}, {"Slice", TranslateSliceOp}, {"Snapshot", TranslateIdentityOp}, {"Softmax", TranslateSoftmaxOp}, diff --git a/ngraph_bridge/ngraph_encapsulate_op_utils.cc b/ngraph_bridge/ngraph_encapsulate_op_utils.cc index d12494e45..ea893160b 100644 --- a/ngraph_bridge/ngraph_encapsulate_op_utils.cc +++ b/ngraph_bridge/ngraph_encapsulate_op_utils.cc @@ -99,10 +99,10 @@ Status GetPipelinedIOTensorsReadyForExecution( get<2>(io_tensors_next_iter)}; if (current_iter_pipeline_depth != (!next_io_tensor_bundle.Id)) { - return errors::Internal("Current Pipeline Depth is ", - current_iter_pipeline_depth, - " and next iter pipeline depth is also ", - next_io_tensor_bundle.Id); + delete shared_data; + return errors::Internal( + "Current Pipeline Depth is ", current_iter_pipeline_depth, + " and next iter pipeline depth is also ", next_io_tensor_bundle.Id); } shared_data->AddNextIOTensorBundleForDeviceTransfer( @@ -154,6 +154,7 @@ Status GetPipelinedIOTensorsReadyForExecution( NGRAPH_VLOG(2) << "[PREFETCH] COMPUTE: Using device tensors"; } shared_data->IncrSkipCount(); + shared_data->Unref(); } } diff --git a/ngraph_bridge/ngraph_executor.cc b/ngraph_bridge/ngraph_executor.cc index 7d4fe2c2a..9ab82b600 100644 --- a/ngraph_bridge/ngraph_executor.cc +++ b/ngraph_bridge/ngraph_executor.cc @@ -294,13 +294,6 @@ NGraphExecutor::CreateCallback(const std::string signature, // Serialize to nGraph if needed if (std::getenv("NGRAPH_ENABLE_SERIALIZE") != nullptr) { - std::string file_name = "tf_function_" + m_node_name + ".json"; - auto status_ser = StringToFile("tf_function_" + m_node_name + ".json", - serialized_ng_func); - if (status_ser != Status::OK()) { - return std::make_pair(status_ser, - std::make_tuple(ng_exec, serialized_ng_func, pts)); - } #if defined NGRAPH_DISTRIBUTED int rank_id; rank_id = ng::get_distributed_interface()->get_rank(); @@ -311,6 +304,13 @@ NGraphExecutor::CreateCallback(const std::string signature, return std::make_pair(status, std::make_tuple(ng_exec, serialized_ng_func, pts)); } +#else + auto status_ser = StringToFile("tf_function_" + m_node_name + ".json", + serialized_ng_func); + if (status_ser != Status::OK()) { + return std::make_pair(status_ser, + std::make_tuple(ng_exec, serialized_ng_func, pts)); + } #endif } // Get NgExecutable @@ -329,7 +329,8 @@ NGraphExecutor::CreateCallback(const std::string signature, Status st = StringToFile("tf_function_error_" + m_node_name + ".json", serialized_ng_func); string status_string = - "Error in compiling op_backend." + + "Error in compiling op_backend with error: " + + status_ng_exec_pair.first.error_message() + (st.ok() ? "" : (" Also error in dumping serialized function: " + st.error_message())); return std::make_pair(errors::Internal(status_string), diff --git a/ngraph_bridge/ngraph_mark_for_clustering.cc b/ngraph_bridge/ngraph_mark_for_clustering.cc index b4aec04fc..b7c8028aa 100644 --- a/ngraph_bridge/ngraph_mark_for_clustering.cc +++ b/ngraph_bridge/ngraph_mark_for_clustering.cc @@ -49,11 +49,6 @@ namespace ngraph_bridge { // "_ngraph_marked_for_clustering" set to "true". Additional metadata (Static // Inputs) for the op is also set. -using ConfirmationFunction = std::function; -using TypeConstraintMap = - std::map>>; -using SetAttributesFunction = std::function; - // Different Checks before we mark for clustering // // Utility function to check if placement on the NGRAPH device has been @@ -75,20 +70,23 @@ static Status CheckIfOutputNode(const Node* node, // Checks if the node's inputs meet all the type constraints static Status TypeConstraintOk(Node* node, - TypeConstraintMap& type_constraint_map, + const TypeConstraintMap& type_constraint_map, bool& type_constraints_ok) { type_constraints_ok = true; - for (auto& name_and_set : type_constraint_map[node->type_string()]) { - auto& type_attr_name = name_and_set.first; - auto& allowed_types = name_and_set.second; + const auto& itr = type_constraint_map.find(node->type_string()); + if (itr != type_constraint_map.end()) { + for (const auto& name_and_set : itr->second) { + auto& type_attr_name = name_and_set.first; + auto& allowed_types = name_and_set.second; - DataType dt; + DataType dt; - if (GetNodeAttr(node->attrs(), type_attr_name, &dt) != Status::OK() || - std::find(allowed_types.begin(), allowed_types.end(), dt) == - allowed_types.end()) { - type_constraints_ok = false; - break; + if (GetNodeAttr(node->attrs(), type_attr_name, &dt) != Status::OK() || + std::find(allowed_types.begin(), allowed_types.end(), dt) == + allowed_types.end()) { + type_constraints_ok = false; + break; + } } } return Status::OK(); @@ -141,7 +139,8 @@ static ConfirmationFunction SimpleConfirmationFunction() { // Check if op is supported by backend using is_supported API Status IsSupportedByBackend( const Node* node, const ng::runtime::Backend* op_backend, - std::map>>& TFtoNgraphOpMap, + const std::map>>& + TFtoNgraphOpMap, bool& is_supported) { is_supported = true; @@ -163,24 +162,89 @@ Status IsSupportedByBackend( return Status::OK(); } -// -// Main entry point for the marking pass. -// -Status MarkForClustering(Graph* graph, const std::set skip_these_nodes, - const string& current_backend) { +const std::map& GetAttributeSetters() { // - // A map of op types (e.g. "Add") to type constraint maps. For (fake) - // example: + // A map of op types (e.g. "Add") to set_attribute functions. These can be + // used to set any additional attributes. For example: // - // type_constraint_map["Cast"]["SrcT"] = {DT_FLOAT, DT_BOOL}; - // type_constraint_map["Cast"]["DstT"] = {DT_DOUBLE, DT_INT16}; + // confirmation_function_map["MyOp"] = [](Node* n) { + // if(n->condition()){ + // int dummy=5; + // n->AddAttr("_ngraph_dummy_attr", dummy); + // } // - // ...would mean that for the "Cast" op, the "SrcT" type variable can be - // DT_FLOAT or DT_BOOL, and the "DstT" type variable can be DT_DOUBLE or - // DT_INT16. + // vector static_input_index =5; + // n->AddAttr("_ngraph_static_inputs", static_input_index); + // return Status::OK(); + // }; // - static TypeConstraintMap type_constraint_map; + static std::map set_attributes_map; + static bool initialized = false; + + if (!initialized) { + // Set Additional Attributes (if any) + set_attributes_map["Any"] = SetStaticInputs({1}); + set_attributes_map["All"] = SetStaticInputs({1}); + set_attributes_map["ArgMax"] = SetStaticInputs({1}); + set_attributes_map["ArgMin"] = SetStaticInputs({1}); + set_attributes_map["AvgPoolGrad"] = SetStaticInputs({0}); + set_attributes_map["ConcatV2"] = SetStaticInputs({-1}); + set_attributes_map["CombinedNonMaxSuppression"] = + SetStaticInputs({2, 3, 4, 5}); + set_attributes_map["Conv2DBackpropFilter"] = SetStaticInputs({1}); + set_attributes_map["Conv2DBackpropInput"] = SetStaticInputs({0}); + set_attributes_map["ExpandDims"] = SetStaticInputs({1}); + set_attributes_map["Fill"] = SetStaticInputs({0}); + set_attributes_map["GatherV2"] = SetStaticInputs({2}); + set_attributes_map["Max"] = SetStaticInputs({1}); + set_attributes_map["Mean"] = SetStaticInputs({1}); + set_attributes_map["Min"] = SetStaticInputs({1}); + set_attributes_map["NonMaxSuppressionV4"] = SetStaticInputs({2, 3, 4}); + set_attributes_map["OneHot"] = SetStaticInputs({1}); + set_attributes_map["Pad"] = SetStaticInputs({1}); + set_attributes_map["Prod"] = SetStaticInputs({1}); + + set_attributes_map["QuantizeAndDequantizeV2"] = SetStaticInputs({1, 2}); + set_attributes_map["QuantizedConcat"] = [](Node* n) { + SetStaticInputs(n, {0}); // the axis + auto num_of_tensors_to_concat = (n->num_inputs() - 1) / 3; + // mark all mins and maxes static + for (int idx = num_of_tensors_to_concat + 1; idx < n->num_inputs(); + idx++) { + SetStaticInputs(n, {idx}); + } + return Status::OK(); + }; + set_attributes_map["QuantizedConcatV2"] = [](Node* n) { + auto num_of_tensors_to_concat = (n->num_inputs() - 1) / 3; + // mark axis, all mins and maxes static + std::vector static_input_vec; + for (int idx = num_of_tensors_to_concat; idx < n->num_inputs(); idx++) { + static_input_vec.push_back(idx); + } + SetStaticInputs(n, static_input_vec); + return Status::OK(); + }; + set_attributes_map["RandomUniform"] = SetStaticInputs({0}); + set_attributes_map["Reshape"] = SetStaticInputs({1}); + set_attributes_map["ResizeBilinear"] = SetStaticInputs({1}); + set_attributes_map["ScatterNd"] = SetStaticInputs({2}); + set_attributes_map["Slice"] = SetStaticInputs({1, 2}); + set_attributes_map["Split"] = SetStaticInputs({0}); + set_attributes_map["SplitV"] = SetStaticInputs({1, 2}); + set_attributes_map["StridedSlice"] = SetStaticInputs({1, 2, 3}); + set_attributes_map["Sum"] = SetStaticInputs({1}); + set_attributes_map["TopKV2"] = SetStaticInputs({1}); + set_attributes_map["Tile"] = SetStaticInputs({1}); + set_attributes_map["Transpose"] = SetStaticInputs({1}); + set_attributes_map["UnsortedSegmentSum"] = SetStaticInputs({2}); + initialized = true; + } + return set_attributes_map; +} + +const std::map& GetConfirmationMap() { // // A map of op types (e.g. "Add") to confirmation functions. These can be // used to check arbitrary constraints. For example: @@ -198,27 +262,431 @@ Status MarkForClustering(Graph* graph, const std::set skip_these_nodes, // The foregoing function checks every "MyOp" node to make sure that it does // not have the attribute "my_unsupported_attr", and rejects placement if it // does. - static std::map confirmation_function_map; + static bool initialized = false; + if (!initialized) { + // + // Initialize confirmation function map. + // + // Please keep these in alphabetical order by op name. + // + confirmation_function_map["Abs"] = SimpleConfirmationFunction(); + confirmation_function_map["Add"] = SimpleConfirmationFunction(); + confirmation_function_map["AddN"] = SimpleConfirmationFunction(); + confirmation_function_map["AddV2"] = SimpleConfirmationFunction(); + confirmation_function_map["Any"] = SimpleConfirmationFunction(); + confirmation_function_map["All"] = SimpleConfirmationFunction(); + confirmation_function_map["ArgMax"] = SimpleConfirmationFunction(); + confirmation_function_map["ArgMin"] = SimpleConfirmationFunction(); + confirmation_function_map["Atan2"] = SimpleConfirmationFunction(); + confirmation_function_map["AvgPool"] = SimpleConfirmationFunction(); + confirmation_function_map["AvgPoolGrad"] = SimpleConfirmationFunction(); + confirmation_function_map["BatchMatMul"] = SimpleConfirmationFunction(); + confirmation_function_map["BatchMatMulV2"] = SimpleConfirmationFunction(); + confirmation_function_map["BiasAdd"] = SimpleConfirmationFunction(); + confirmation_function_map["BiasAddGrad"] = SimpleConfirmationFunction(); + confirmation_function_map["Cast"] = SimpleConfirmationFunction(); + confirmation_function_map["ConcatV2"] = SimpleConfirmationFunction(); + confirmation_function_map["Const"] = SimpleConfirmationFunction(); + confirmation_function_map["Conv2D"] = SimpleConfirmationFunction(); + confirmation_function_map["Conv2DBackpropFilter"] = + SimpleConfirmationFunction(); + confirmation_function_map["Conv2DBackpropInput"] = + SimpleConfirmationFunction(); + confirmation_function_map["Conv3D"] = SimpleConfirmationFunction(); + confirmation_function_map["CropAndResize"] = SimpleConfirmationFunction(); + confirmation_function_map["Cos"] = SimpleConfirmationFunction(); + confirmation_function_map["Cumsum"] = SimpleConfirmationFunction(); + confirmation_function_map["DepthwiseConv2dNative"] = + SimpleConfirmationFunction(); + confirmation_function_map["DepthToSpace"] = [](Node* n, bool* result) { + std::string tf_data_format; + TF_RETURN_IF_ERROR( + GetNodeAttr(n->attrs(), "data_format", &tf_data_format)); + *result = tf_data_format != "NCHW_VECT_C"; + return Status::OK(); + }; + confirmation_function_map["Dequantize"] = [](Node* n, bool* result) { + string mode; + TF_RETURN_IF_ERROR(GetNodeAttr(n->attrs(), "mode", &mode)); + *result = (mode.compare("SCALED") == 0); + return Status::OK(); + }; + confirmation_function_map["Equal"] = SimpleConfirmationFunction(); + confirmation_function_map["Exp"] = SimpleConfirmationFunction(); + confirmation_function_map["ExpandDims"] = SimpleConfirmationFunction(); + confirmation_function_map["Fill"] = SimpleConfirmationFunction(); + confirmation_function_map["Floor"] = SimpleConfirmationFunction(); + confirmation_function_map["FloorDiv"] = SimpleConfirmationFunction(); + confirmation_function_map["FloorMod"] = SimpleConfirmationFunction(); + confirmation_function_map["FusedBatchNorm"] = SimpleConfirmationFunction(); + confirmation_function_map["FusedBatchNormV2"] = + SimpleConfirmationFunction(); + confirmation_function_map["FusedBatchNormV3"] = + SimpleConfirmationFunction(); + confirmation_function_map["FusedBatchNormGrad"] = [](Node* n, + bool* result) { + TF_RETURN_IF_ERROR(GetNodeAttr(n->attrs(), "is_training", result)); + return Status::OK(); + }; + confirmation_function_map["FusedBatchNormGradV3"] = [](Node* n, + bool* result) { + TF_RETURN_IF_ERROR(GetNodeAttr(n->attrs(), "is_training", result)); + return Status::OK(); + }; + confirmation_function_map["_FusedConv2D"] = SimpleConfirmationFunction(); + confirmation_function_map["GatherNd"] = SimpleConfirmationFunction(); + confirmation_function_map["GatherV2"] = SimpleConfirmationFunction(); + confirmation_function_map["_FusedMatMul"] = + SimpleConfirmationFunction(); // TODO accept under all conditions? + // check? + confirmation_function_map["Greater"] = SimpleConfirmationFunction(); + confirmation_function_map["GreaterEqual"] = SimpleConfirmationFunction(); +#if defined NGRAPH_DISTRIBUTED + confirmation_function_map["HorovodAllreduce"] = + SimpleConfirmationFunction(); + confirmation_function_map["HorovodBroadcast"] = + SimpleConfirmationFunction(); +#endif + confirmation_function_map["Identity"] = SimpleConfirmationFunction(); + confirmation_function_map["IsFinite"] = SimpleConfirmationFunction(); + confirmation_function_map["L2Loss"] = SimpleConfirmationFunction(); + confirmation_function_map["LogSoftmax"] = SimpleConfirmationFunction(); + confirmation_function_map["Less"] = SimpleConfirmationFunction(); + confirmation_function_map["LessEqual"] = SimpleConfirmationFunction(); + confirmation_function_map["Log"] = SimpleConfirmationFunction(); + confirmation_function_map["LogicalAnd"] = SimpleConfirmationFunction(); + confirmation_function_map["LogicalNot"] = SimpleConfirmationFunction(); + confirmation_function_map["LogicalOr"] = SimpleConfirmationFunction(); + confirmation_function_map["MatMul"] = SimpleConfirmationFunction(); + confirmation_function_map["Max"] = SimpleConfirmationFunction(); + confirmation_function_map["Maximum"] = SimpleConfirmationFunction(); + confirmation_function_map["MaxPool"] = SimpleConfirmationFunction(); + confirmation_function_map["MaxPool3D"] = SimpleConfirmationFunction(); + confirmation_function_map["MaxPoolGrad"] = SimpleConfirmationFunction(); + confirmation_function_map["Mean"] = SimpleConfirmationFunction(); + confirmation_function_map["Min"] = SimpleConfirmationFunction(); + confirmation_function_map["Minimum"] = SimpleConfirmationFunction(); + confirmation_function_map["Mul"] = SimpleConfirmationFunction(); + confirmation_function_map["Neg"] = SimpleConfirmationFunction(); + confirmation_function_map["NoOp"] = SimpleConfirmationFunction(); + confirmation_function_map["OneHot"] = SimpleConfirmationFunction(); + confirmation_function_map["Pad"] = SimpleConfirmationFunction(); + confirmation_function_map["Pow"] = SimpleConfirmationFunction(); + confirmation_function_map["PreventGradient"] = SimpleConfirmationFunction(); + confirmation_function_map["Prod"] = SimpleConfirmationFunction(); + confirmation_function_map["Rank"] = SimpleConfirmationFunction(); + confirmation_function_map["RandomUniform"] = SimpleConfirmationFunction(); + confirmation_function_map["QuantizeAndDequantizeV2"] = [](Node* n, + bool* result) { + // accept only when num_bits == 8 and range is given + bool range_given; + TF_RETURN_IF_ERROR(GetNodeAttr(n->attrs(), "range_given", &range_given)); + int num_bits; + TF_RETURN_IF_ERROR(GetNodeAttr(n->attrs(), "num_bits", &num_bits)); + *result = (num_bits == 8) && range_given; + return Status::OK(); + }; + confirmation_function_map["QuantizedAvgPool"] = + SimpleConfirmationFunction(); + confirmation_function_map["QuantizedConcat"] = SimpleConfirmationFunction(); + confirmation_function_map["QuantizedConcatV2"] = + SimpleConfirmationFunction(); + confirmation_function_map["QuantizedConv2DWithBiasAndReluAndRequantize"] = + SimpleConfirmationFunction(); + confirmation_function_map["QuantizedConv2DWithBiasAndRequantize"] = + SimpleConfirmationFunction(); + confirmation_function_map + ["QuantizedConv2DWithBiasSignedSumAndReluAndRequantize"] = + SimpleConfirmationFunction(); + confirmation_function_map + ["QuantizedConv2DWithBiasSumAndReluAndRequantize"] = + SimpleConfirmationFunction(); + confirmation_function_map["QuantizedMaxPool"] = + SimpleConfirmationFunction(); + confirmation_function_map["QuantizeV2"] = [](Node* n, bool* result) { + string mode; + TF_RETURN_IF_ERROR(GetNodeAttr(n->attrs(), "mode", &mode)); + *result = (mode.compare("SCALED") == 0); + return Status::OK(); + }; + confirmation_function_map["RealDiv"] = SimpleConfirmationFunction(); + confirmation_function_map["Reciprocal"] = SimpleConfirmationFunction(); + confirmation_function_map["Relu"] = SimpleConfirmationFunction(); + confirmation_function_map["Relu6"] = SimpleConfirmationFunction(); + confirmation_function_map["ReluGrad"] = SimpleConfirmationFunction(); + confirmation_function_map["Reshape"] = SimpleConfirmationFunction(); + confirmation_function_map["ResizeBilinear"] = SimpleConfirmationFunction(); + confirmation_function_map["Rsqrt"] = SimpleConfirmationFunction(); + confirmation_function_map["RsqrtGrad"] = SimpleConfirmationFunction(); + confirmation_function_map["ScatterNd"] = SimpleConfirmationFunction(); + confirmation_function_map["Select"] = SimpleConfirmationFunction(); + confirmation_function_map["Shape"] = SimpleConfirmationFunction(); + confirmation_function_map["Sigmoid"] = SimpleConfirmationFunction(); + confirmation_function_map["SigmoidGrad"] = SimpleConfirmationFunction(); + confirmation_function_map["Sign"] = SimpleConfirmationFunction(); + confirmation_function_map["Sin"] = SimpleConfirmationFunction(); + confirmation_function_map["Size"] = SimpleConfirmationFunction(); + confirmation_function_map["Slice"] = SimpleConfirmationFunction(); + confirmation_function_map["Snapshot"] = SimpleConfirmationFunction(); + confirmation_function_map["Softmax"] = SimpleConfirmationFunction(); + confirmation_function_map["SoftmaxCrossEntropyWithLogits"] = + SimpleConfirmationFunction(); + confirmation_function_map["Softplus"] = SimpleConfirmationFunction(); + confirmation_function_map["SpaceToDepth"] = + confirmation_function_map["DepthToSpace"]; + confirmation_function_map["SparseSoftmaxCrossEntropyWithLogits"] = + SimpleConfirmationFunction(); + confirmation_function_map["Split"] = SimpleConfirmationFunction(); + confirmation_function_map["SplitV"] = SimpleConfirmationFunction(); + confirmation_function_map["Sqrt"] = SimpleConfirmationFunction(); + confirmation_function_map["Square"] = SimpleConfirmationFunction(); + confirmation_function_map["SquaredDifference"] = + SimpleConfirmationFunction(); + confirmation_function_map["Squeeze"] = SimpleConfirmationFunction(); + confirmation_function_map["StridedSlice"] = SimpleConfirmationFunction(); + confirmation_function_map["Pack"] = SimpleConfirmationFunction(); + confirmation_function_map["Sub"] = SimpleConfirmationFunction(); + confirmation_function_map["Sum"] = SimpleConfirmationFunction(); + confirmation_function_map["Tanh"] = SimpleConfirmationFunction(); + confirmation_function_map["TanhGrad"] = SimpleConfirmationFunction(); + confirmation_function_map["Tile"] = SimpleConfirmationFunction(); + confirmation_function_map["TopKV2"] = [](Node* n, bool* result) { + bool sorted = true; + TF_RETURN_IF_ERROR(GetNodeAttr(n->attrs(), "sorted", &sorted)); + // sorted = false is not supported right now, it falls back to TF if set + // to false. + *result = sorted; + return Status::OK(); + }; + confirmation_function_map["Transpose"] = SimpleConfirmationFunction(); + confirmation_function_map["Unpack"] = SimpleConfirmationFunction(); + confirmation_function_map["UnsortedSegmentSum"] = + SimpleConfirmationFunction(); + confirmation_function_map["ZerosLike"] = SimpleConfirmationFunction(); + initialized = true; + } + return confirmation_function_map; +} + +const TypeConstraintMap& GetTypeConstraintMap() { // - // A map of op types (e.g. "Add") to set_attribute functions. These can be - // used to set any additional attributes. For example: + // A map of op types (e.g. "Add") to type constraint maps. For (fake) + // example: // - // confirmation_function_map["MyOp"] = [](Node* n) { - // if(n->condition()){ - // int dummy=5; - // n->AddAttr("_ngraph_dummy_attr", dummy); - // } + // type_constraint_map["Cast"]["SrcT"] = {DT_FLOAT, DT_BOOL}; + // type_constraint_map["Cast"]["DstT"] = {DT_DOUBLE, DT_INT16}; // - // vector static_input_index =5; - // n->AddAttr("_ngraph_static_inputs", static_input_index); - // return Status::OK(); - // }; + // ...would mean that for the "Cast" op, the "SrcT" type variable can be + // DT_FLOAT or DT_BOOL, and the "DstT" type variable can be DT_DOUBLE or + // DT_INT16. // + static bool initialized = false; + static TypeConstraintMap type_constraint_map; + if (!initialized) { + // + // Initialize type constraint map. + // + type_constraint_map["Abs"]["T"] = NGraphNumericDTypes(); + type_constraint_map["Add"]["T"] = NGraphNumericDTypes(); + type_constraint_map["AddN"]["T"] = NGraphNumericDTypes(); + type_constraint_map["AddV2"]["T"] = NGraphNumericDTypes(); + type_constraint_map["Any"]["Tidx"] = NGraphIndexDTypes(); + type_constraint_map["All"]["Tidx"] = NGraphIndexDTypes(); + type_constraint_map["ArgMax"]["T"] = NGraphNumericDTypes(); + type_constraint_map["ArgMax"]["Tidx"] = NGraphIndexDTypes(); + type_constraint_map["ArgMin"]["T"] = NGraphNumericDTypes(); + type_constraint_map["ArgMin"]["Tidx"] = NGraphIndexDTypes(); + type_constraint_map["Atan2"]["T"] = NGraphRealDTypes(); + type_constraint_map["AvgPool"]["T"] = NGraphNumericDTypes(); + type_constraint_map["AvgPoolGrad"]["T"] = NGraphNumericDTypes(); + type_constraint_map["BatchMatMul"]["T"] = NGraphNumericDTypes(); + type_constraint_map["BatchMatMulV2"]["T"] = NGraphNumericDTypes(); + type_constraint_map["BiasAdd"]["T"] = NGraphNumericDTypes(); + type_constraint_map["BiasAddGrad"]["T"] = NGraphNumericDTypes(); + type_constraint_map["Cast"]["SrcT"] = NGraphDTypes(); + type_constraint_map["Cast"]["DstT"] = NGraphDTypes(); + type_constraint_map["ConcatV2"]["T"] = NGraphDTypes(); + type_constraint_map["ConcatV2"]["Tidx"] = NGraphIndexDTypes(); + type_constraint_map["Const"]["dtype"] = NGraphDTypes(); + type_constraint_map["Conv2D"]["T"] = NGraphNumericDTypes(); + type_constraint_map["Conv2DBackpropInput"]["T"] = NGraphNumericDTypes(); + type_constraint_map["Conv3D"]["T"] = NGraphNumericDTypes(); + type_constraint_map["CropAndResize"]["T"] = NGraphNumericDTypes(); + type_constraint_map["Cos"]["T"] = NGraphRealDTypes(); + type_constraint_map["Cumsum"]["T"] = NGraphNumericDTypes(); + type_constraint_map["Cumsum"]["Tidx"] = NGraphIndexDTypes(); + type_constraint_map["DepthToSpace"]["T"] = NGraphDTypes(); + type_constraint_map["DepthwiseConv2dNative"]["T"] = NGraphNumericDTypes(); + type_constraint_map["Dequantize"]["T"] = NGraphSupportedQuantizedDTypes(); + type_constraint_map["Equal"]["T"] = NGraphDTypes(); + type_constraint_map["Exp"]["T"] = NGraphNumericDTypes(); + type_constraint_map["ExpandDims"]["T"] = NGraphDTypes(); + type_constraint_map["Floor"]["T"] = NGraphNumericDTypes(); + type_constraint_map["FloorDiv"]["T"] = NGraphNumericDTypes(); + type_constraint_map["FloorMod"]["T"] = NGraphNumericDTypes(); + type_constraint_map["FusedBatchNorm"]["T"] = NGraphNumericDTypes(); + // TODO (mingshan): FusedBatchNormV2, V3 supports DT_HALF,DT_BFLOAT16, + // DT_FLOAT + type_constraint_map["FusedBatchNormV2"]["T"] = {DT_FLOAT}; + type_constraint_map["FusedBatchNormV3"]["T"] = {DT_FLOAT}; + type_constraint_map["FusedBatchNormGrad"]["T"] = NGraphNumericDTypes(); + type_constraint_map["GatherNd"]["Tparams"] = {DT_FLOAT}; // NGraphDTypes(); + type_constraint_map["GatherNd"]["Tindices"] = NGraphIndexDTypes(); + type_constraint_map["FusedBatchNormGradV3"]["T"] = NGraphNumericDTypes(); + type_constraint_map["GatherV2"]["Tparams"] = NGraphDTypes(); + type_constraint_map["GatherV2"]["Tindices"] = NGraphIndexDTypes(); + type_constraint_map["GatherV2"]["Taxis"] = NGraphIndexDTypes(); + type_constraint_map["_FusedConv2D"]["T"] = NGraphRealDTypes(); + type_constraint_map["_FusedMatMul"]["T"] = NGraphRealDTypes(); + type_constraint_map["Greater"]["T"] = NGraphDTypes(); + type_constraint_map["GreaterEqual"]["T"] = NGraphDTypes(); +#if defined NGRAPH_DISTRIBUTED + type_constraint_map["HorovodAllreduce"]["T"] = NGraphNumericDTypes(); + type_constraint_map["HorovodBroadcast"]["T"] = NGraphNumericDTypes(); +#endif + type_constraint_map["Identity"]["T"] = NGraphDTypes(); + type_constraint_map["IsFinite"]["T"] = NGraphRealDTypes(); + type_constraint_map["L2Loss"]["T"] = NGraphNumericDTypes(); + type_constraint_map["LogSoftmax"]["T"] = NGraphRealDTypes(); + type_constraint_map["Less"]["T"] = NGraphDTypes(); + type_constraint_map["LessEqual"]["T"] = NGraphDTypes(); + type_constraint_map["Log"]["T"] = NGraphNumericDTypes(); + // LogicalAnd and LogicalNot have no type attributes ("T", if it existed, + // would always be bool). + type_constraint_map["MatMul"]["T"] = NGraphNumericDTypes(); + type_constraint_map["Max"]["T"] = NGraphNumericDTypes(); + type_constraint_map["Max"]["Tidx"] = NGraphIndexDTypes(); + type_constraint_map["Maximum"]["T"] = NGraphNumericDTypes(); + type_constraint_map["MaxPool"]["T"] = NGraphNumericDTypes(); + type_constraint_map["MaxPool3D"]["T"] = NGraphNumericDTypes(); + type_constraint_map["MaxPoolGrad"]["T"] = NGraphNumericDTypes(); + type_constraint_map["Mean"]["T"] = NGraphNumericDTypes(); + type_constraint_map["Mean"]["Tidx"] = NGraphIndexDTypes(); + type_constraint_map["Min"]["T"] = NGraphNumericDTypes(); + type_constraint_map["Min"]["Tidx"] = NGraphIndexDTypes(); + type_constraint_map["Minimum"]["T"] = NGraphNumericDTypes(); + type_constraint_map["Mul"]["T"] = NGraphNumericDTypes(); + type_constraint_map["Neg"]["T"] = NGraphNumericDTypes(); + type_constraint_map["NonMaxSuppressionV4"]["T"] = { + DT_FLOAT}; // TF allows half too + type_constraint_map["OneHot"]["T"] = NGraphDTypes(); + type_constraint_map["Pack"]["T"] = NGraphDTypes(); + type_constraint_map["RandomUniform"]["T"] = NGraphDTypes(); + type_constraint_map["Pad"]["T"] = NGraphDTypes(); + type_constraint_map["Pad"]["Tpaddings"] = NGraphIndexDTypes(); + type_constraint_map["Pow"]["T"] = NGraphNumericDTypes(); + type_constraint_map["PreventGradient"]["T"] = NGraphDTypes(); + type_constraint_map["Prod"]["T"] = NGraphNumericDTypes(); + type_constraint_map["Prod"]["Tidx"] = NGraphIndexDTypes(); + type_constraint_map["QuantizeAndDequantizeV2"]["T"] = NGraphRealDTypes(); + type_constraint_map["QuantizedAvgPool"]["T"] = + NGraphSupportedQuantizedDTypes(); + type_constraint_map["QuantizedConcat"]["T"] = + NGraphSupportedQuantizedDTypes(); + type_constraint_map["QuantizedConcatV2"]["T"] = + NGraphSupportedQuantizedDTypes(); + type_constraint_map["QuantizedConv2DWithBiasAndReluAndRequantize"] + ["Tinput"] = NGraphSupportedQuantizedDTypes(); + type_constraint_map["QuantizedConv2DWithBiasAndReluAndRequantize"] + ["Tfilter"] = NGraphSupportedQuantizedDTypes(); + type_constraint_map["QuantizedConv2DWithBiasAndReluAndRequantize"] + ["Tbias"] = NGraphBiasDTypes(); + // TODO: check if any other type constraint is required + // https://github.com/tensorflow/tensorflow/blob/c95ca05536144451ef78ca6e2c15f0f65ebaaf95/tensorflow/core/ops/nn_ops.cc#L2780 + type_constraint_map["QuantizedConv2DWithBiasSignedSumAndReluAndRequantize"] + ["Tinput"] = NGraphSupportedQuantizedDTypes(); + type_constraint_map["QuantizedConv2DWithBiasSignedSumAndReluAndRequantize"] + ["Tsummand"] = NGraphSupportedQuantizedDTypes(); + type_constraint_map["QuantizedConv2DWithBiasSignedSumAndReluAndRequantize"] + ["Tfilter"] = NGraphSupportedQuantizedDTypes(); + type_constraint_map["QuantizedConv2DWithBiasSignedSumAndReluAndRequantize"] + ["Tbias"] = NGraphBiasDTypes(); + type_constraint_map["QuantizedConv2DWithBiasSumAndReluAndRequantize"] + ["Tinput"] = NGraphSupportedQuantizedDTypes(); + type_constraint_map["QuantizedConv2DWithBiasSumAndReluAndRequantize"] + ["Tsummand"] = NGraphSupportedQuantizedDTypes(); + type_constraint_map["QuantizedConv2DWithBiasSumAndReluAndRequantize"] + ["Tfilter"] = NGraphSupportedQuantizedDTypes(); + type_constraint_map["QuantizedConv2DWithBiasSumAndReluAndRequantize"] + ["Tbias"] = NGraphBiasDTypes(); + type_constraint_map["QuantizedConv2DWithBiasAndRequantize"]["Tinput"] = + NGraphSupportedQuantizedDTypes(); + type_constraint_map["QuantizedConv2DWithBiasAndRequantize"]["Tfilter"] = + NGraphSupportedQuantizedDTypes(); + type_constraint_map["QuantizedConv2DWithBiasAndRequantize"]["Tbias"] = + NGraphBiasDTypes(); + type_constraint_map["QuantizedMaxPool"]["T"] = + NGraphSupportedQuantizedDTypes(); + type_constraint_map["QuantizeV2"]["T"] = NGraphSupportedQuantizedDTypes(); + type_constraint_map["Rank"]["T"] = NGraphNumericDTypes(); + type_constraint_map["RealDiv"]["T"] = NGraphNumericDTypes(); + type_constraint_map["Reciprocal"]["T"] = NGraphNumericDTypes(); + type_constraint_map["Relu"]["T"] = NGraphNumericDTypes(); + type_constraint_map["Relu6"]["T"] = NGraphNumericDTypes(); + type_constraint_map["ReluGrad"]["T"] = NGraphNumericDTypes(); + type_constraint_map["Reshape"]["T"] = NGraphDTypes(); + type_constraint_map["Reshape"]["Tshape"] = NGraphIndexDTypes(); + type_constraint_map["ResizeBilinear"]["T"] = NGraphNumericDTypes(); + type_constraint_map["Rsqrt"]["T"] = NGraphDTypes(); + type_constraint_map["RsqrtGrad"]["T"] = NGraphRealDTypes(); + type_constraint_map["ScatterNd"]["T"] = NGraphDTypes(); + type_constraint_map["ScatterNd"]["Tindices"] = NGraphIndexDTypes(); + type_constraint_map["Select"]["T"] = NGraphDTypes(); + type_constraint_map["Shape"]["T"] = NGraphDTypes(); + type_constraint_map["Shape"]["out_type"] = NGraphIndexDTypes(); + type_constraint_map["Sigmoid"]["T"] = NGraphNumericDTypes(); + type_constraint_map["SigmoidGrad"]["T"] = NGraphNumericDTypes(); + type_constraint_map["Sign"]["T"] = NGraphNumericDTypes(); + type_constraint_map["Sin"]["T"] = NGraphRealDTypes(); + type_constraint_map["Size"]["T"] = NGraphDTypes(); + type_constraint_map["Size"]["out_type"] = NGraphIndexDTypes(); + type_constraint_map["Slice"]["T"] = NGraphDTypes(); + type_constraint_map["Slice"]["Index"] = NGraphIndexDTypes(); + type_constraint_map["Snapshot"]["T"] = NGraphDTypes(); + type_constraint_map["Softmax"]["T"] = NGraphNumericDTypes(); + // For SoftmaxCrossEntropyWithLogits, see + // https://github.com/tensorflow/tensorflow/blob/c95ca05536144451ef78ca6e2c15f0f65ebaaf95/tensorflow/core/ops/nn_ops.cc#L1096 + type_constraint_map["SoftmaxCrossEntropyWithLogits"]["T"] = + NGraphRealDTypes(); + type_constraint_map["Softplus"]["T"] = NGraphRealDTypes(); + type_constraint_map["SpaceToDepth"]["T"] = NGraphDTypes(); + type_constraint_map["SparseSoftmaxCrossEntropyWithLogits"]["T"] = + NGraphRealDTypes(); + type_constraint_map["SparseSoftmaxCrossEntropyWithLogits"]["Tlabels"] = + NGraphNumericDTypes(); + type_constraint_map["Split"]["T"] = NGraphDTypes(); + type_constraint_map["SplitV"]["T"] = NGraphDTypes(); + type_constraint_map["SplitV"]["Tlen"] = NGraphIndexDTypes(); + type_constraint_map["Sqrt"]["T"] = NGraphDTypes(); + type_constraint_map["Square"]["T"] = NGraphDTypes(); + type_constraint_map["SquaredDifference"]["T"] = NGraphDTypes(); + type_constraint_map["Squeeze"]["T"] = NGraphDTypes(); + type_constraint_map["StridedSlice"]["T"] = NGraphDTypes(); + type_constraint_map["StridedSlice"]["Index"] = NGraphIndexDTypes(); + type_constraint_map["Sub"]["T"] = NGraphNumericDTypes(); + type_constraint_map["Sum"]["T"] = NGraphNumericDTypes(); + type_constraint_map["Sum"]["Tidx"] = NGraphIndexDTypes(); + type_constraint_map["Tanh"]["T"] = NGraphNumericDTypes(); + type_constraint_map["TanhGrad"]["T"] = NGraphNumericDTypes(); + type_constraint_map["Tile"]["T"] = NGraphNumericDTypes(); + type_constraint_map["Tile"]["Tmultiples"] = NGraphIndexDTypes(); + type_constraint_map["TopKV2"]["T"] = NGraphNumericDTypes(); + type_constraint_map["Transpose"]["T"] = NGraphDTypes(); + type_constraint_map["Transpose"]["Tperm"] = NGraphIndexDTypes(); + type_constraint_map["Unpack"]["T"] = NGraphDTypes(); + type_constraint_map["UnsortedSegmentSum"]["T"] = NGraphNumericDTypes(); + type_constraint_map["UnsortedSegmentSum"]["Tindices"] = NGraphIndexDTypes(); + type_constraint_map["UnsortedSegmentSum"]["Tnumsegments"] = + NGraphIndexDTypes(); + initialized = true; + } + return type_constraint_map; +} - static std::map set_attributes_map; - +const std::map>>& +GetTFToNgOpMap() { // Constant Op, ReluGrad Op do not have default Constructor // in ngraph, so passing a dummy node auto constant = ngraph::op::Constant::create(ngraph::element::f32, @@ -232,348 +700,398 @@ Status MarkForClustering(Graph* graph, const std::set skip_these_nodes, // are supported by backend // Update this Map if a new TF Op translation is // implemented or a new Ngraph Op has been added - static std::map>> TFtoNgraphOpMap{ - {"Abs", {std::make_shared()}}, - {"Add", {std::make_shared()}}, - {"AddN", {std::make_shared()}}, - {"AddV2", {std::make_shared()}}, - {"Any", {std::make_shared()}}, - {"All", {std::make_shared()}}, - {"ArgMax", {std::make_shared()}}, - {"ArgMin", {std::make_shared()}}, - {"AvgPool", {std::make_shared()}}, - {"AvgPoolGrad", {std::make_shared()}}, - {"BatchMatMul", - {std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared()}}, - {"BatchMatMulV2", - {std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared()}}, - {"BiasAdd", - {std::make_shared(), - std::make_shared()}}, - {"BiasAddGrad", {std::make_shared()}}, - {"Cast", {std::make_shared()}}, - {"ConcatV2", {std::make_shared()}}, - {"Const", {constant}}, - {"Conv2D", - {std::make_shared(), - std::make_shared()}}, - {"Conv2DBackpropFilter", - {std::make_shared(), - std::make_shared()}}, - {"Conv2DBackpropInput", - {std::make_shared(), - std::make_shared()}}, - {"Conv3D", - {std::make_shared(), - std::make_shared()}}, - {"Cos", {std::make_shared()}}, - {"DepthToSpace", {std::make_shared()}}, - {"DepthwiseConv2dNative", - {std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared()}}, - {"Dequantize", {std::make_shared()}}, - {"Equal", {std::make_shared()}}, - {"Exp", {std::make_shared()}}, - {"ExpandDims", {std::make_shared()}}, - {"Fill", {std::make_shared()}}, - {"Floor", {std::make_shared()}}, - {"FloorDiv", {std::make_shared()}}, - {"FloorMod", - {std::make_shared(), - std::make_shared(), - std::make_shared()}}, - {"FusedBatchNorm", - {std::make_shared(), - std::make_shared(), constant, - std::make_shared(), - std::make_shared()}}, - {"FusedBatchNormV2", - {std::make_shared(), - std::make_shared(), constant, - std::make_shared(), - std::make_shared()}}, - {"FusedBatchNormV3", - {std::make_shared(), - std::make_shared(), constant, - std::make_shared(), - std::make_shared()}}, - {"FusedBatchNormGrad", - {constant, std::make_shared(), - std::make_shared()}}, - {"FusedBatchNormGradV3", - {constant, std::make_shared(), - std::make_shared()}}, - {"GatherNd", {std::make_shared()}}, - {"GatherV2", {std::make_shared()}}, - {"_FusedConv2D", - {std::make_shared(), - std::make_shared(), constant, - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared()}}, - {"_FusedMatMul", - {std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), constant, - std::make_shared(), - std::make_shared()}}, - {"Greater", {std::make_shared()}}, - {"GreaterEqual", {std::make_shared()}}, - {"Identity", {}}, - {"IsFinite", - {constant, std::make_shared(), - std::make_shared(), - std::make_shared()}}, - {"L2Loss", - {constant, std::make_shared(), - std::make_shared(), - std::make_shared()}}, - {"LogSoftmax", - {std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared()}}, - {"Less", {std::make_shared()}}, - {"LessEqual", {std::make_shared()}}, - {"Log", {std::make_shared()}}, - {"LogicalAnd", {std::make_shared()}}, - {"LogicalNot", {std::make_shared()}}, - {"LogicalOr", {std::make_shared()}}, - {"MatMul", - {std::make_shared(), - std::make_shared()}}, - {"Max", {std::make_shared()}}, - {"Maximum", {std::make_shared()}}, - {"MaxPool", - {std::make_shared(), - std::make_shared()}}, - {"MaxPool3D", - {std::make_shared(), - std::make_shared()}}, - {"MaxPoolGrad", - {std::make_shared(), - std::make_shared()}}, - {"Mean", - {std::make_shared(), constant, - std::make_shared(), - std::make_shared()}}, - {"Min", {std::make_shared()}}, - {"Minimum", {std::make_shared()}}, - {"Mul", {std::make_shared()}}, - {"Neg", {std::make_shared()}}, - {"OneHot", - {std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared()}}, - {"Pack", - {std::make_shared(), - std::make_shared()}}, - {"Pad", {constant, std::make_shared()}}, - {"Pow", {std::make_shared()}}, - {"PreventGradient", {}}, - {"Prod", {std::make_shared()}}, - {"QuantizeAndDequantizeV2", - {constant, std::make_shared(), - std::make_shared()}}, - // Next few are CPU only ops - {"QuantizedAvgPool", - {std::make_shared(), - std::make_shared()}}, - {"QuantizedConcat", - {constant, std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared()}}, - {"QuantizedConcatV2", - {constant, std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared()}}, - {"QuantizedConv2DWithBiasAndReluAndRequantize", - {constant, std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared()}}, - {"QuantizedConv2DWithBiasAndRequantize", - {constant, std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared()}}, - {"QuantizedConv2DWithBiasSignedSumAndReluAndRequantize", - {constant, std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared()}}, - {"QuantizedConv2DWithBiasSumAndReluAndRequantize", - {constant, std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared()}}, - {"QuantizedMaxPool", - {std::make_shared(), - std::make_shared()}}, - // End of CPU only ops - {"QuantizeV2", - {constant, std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared()}}, - { - "RandomUniform", - {constant, std::make_shared()}, - }, - {"Rank", {constant}}, - {"RealDiv", {std::make_shared()}}, - {"Reciprocal", {constant, std::make_shared()}}, - {"Relu", {std::make_shared()}}, - {"Relu6", - {constant, std::make_shared(), - std::make_shared()}}, - {"ReluGrad", {relu}}, - {"Reshape", {std::make_shared()}}, - {"Rsqrt", {constant, std::make_shared()}}, - {"RsqrtGrad", - {constant, std::make_shared(), - std::make_shared()}}, - {"Select", - {std::make_shared(), - std::make_shared(), - std::make_shared()}}, - {"Reshape", {constant}}, - {"Shape", {constant}}, - {"Sigmoid", - {constant, std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared()}}, - {"SigmoidGrad", - {constant, std::make_shared(), - std::make_shared()}}, - {"Sin", {std::make_shared()}}, - {"Size", {constant}}, - {"Sign", {std::make_shared()}}, - {"Slice", {std::make_shared()}}, - {"Snapshot", {}}, - {"Softmax", {std::make_shared()}}, - {"SoftmaxCrossEntropyWithLogits", - {std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared()}}, - {"Softplus", - {constant, std::make_shared(), - std::make_shared(), - std::make_shared()}}, - {"SpaceToDepth", - {std::make_shared(), - std::make_shared()}}, - {"SparseSoftmaxCrossEntropyWithLogits", - {std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared(), - std::make_shared()}}, - {"Split", {std::make_shared()}}, - {"SplitV", {std::make_shared()}}, - {"Sqrt", {std::make_shared()}}, - {"Square", {std::make_shared()}}, - {"SquaredDifference", - {std::make_shared(), - std::make_shared()}}, - {"Squeeze", {std::make_shared()}}, - {"StridedSlice", - {std::make_shared(), - std::make_shared(), - std::make_shared()}}, - {"Sub", {std::make_shared()}}, - {"Sum", {std::make_shared()}}, - {"Tanh", {std::make_shared()}}, - {"TanhGrad", - {constant, std::make_shared(), - std::make_shared()}}, - {"Tile", {constant, std::make_shared()}}, - {"TopKV2", - {std::make_shared(), - std::make_shared()}}, - {"Transpose", {constant, std::make_shared()}}, - {"UnsortedSegmentSum", - {constant, std::make_shared()}}, - {"Unpack", - {std::make_shared(), - std::make_shared()}}, - {"ZerosLike", {constant}}, - {"HorovodAllreduce", {std::make_shared()}}, - {"HorovodBroadcast", - {std::make_shared()}}, - {"NoOp", {}}, + static std::map>> TFtoNgraphOpMap { + {"Abs", {std::make_shared()}}, + {"Add", {std::make_shared()}}, + {"AddN", {std::make_shared()}}, + {"AddV2", + {std::make_shared(), + std::make_shared(), + std::make_shared()}}, + {"Any", + {std::make_shared(), + std::make_shared(), constant, + std::make_shared()}}, + {"All", + {std::make_shared(), + std::make_shared(), constant, + std::make_shared()}}, + {"ArgMax", {std::make_shared()}}, + {"ArgMin", {std::make_shared()}}, + {"Atan2", {std::make_shared()}}, + {"AvgPool", {std::make_shared()}}, + {"AvgPoolGrad", {std::make_shared()}}, + {"BatchMatMul", + {std::make_shared(), + std::make_shared(), + std::make_shared()}}, + {"BatchMatMulV2", + {std::make_shared(), + std::make_shared(), + std::make_shared()}}, + {"BiasAdd", + {std::make_shared(), + std::make_shared()}}, + {"BiasAddGrad", {std::make_shared(), constant}}, + {"Cast", {std::make_shared()}}, + {"ConcatV2", {std::make_shared()}}, + {"Const", {constant}}, {"Conv2D", + {std::make_shared(), + std::make_shared()}}, + {"Conv2DBackpropFilter", + {std::make_shared(), + std::make_shared()}}, + {"Conv2DBackpropInput", + {std::make_shared(), + std::make_shared()}}, + {"Conv3D", + {std::make_shared(), + std::make_shared()}}, + {"Cos", {std::make_shared()}}, + {"CropAndResize", {std::make_shared()}}, + {"Cumsum", {std::make_shared()}}, + {"DepthToSpace", {std::make_shared()}}, + {"DepthwiseConv2dNative", + {std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared()}}, + {"Dequantize", + {std::make_shared(), constant, + std::make_shared(), + std::make_shared(), + std::make_shared()}}, + {"Equal", {std::make_shared()}}, + {"Exp", {std::make_shared()}}, + {"ExpandDims", {std::make_shared()}}, + {"Fill", {std::make_shared()}}, + {"Floor", {std::make_shared()}}, + {"FloorDiv", + {std::make_shared(), + std::make_shared(), + std::make_shared()}}, + {"FloorMod", + {std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared()}}, + {"FusedBatchNorm", + {std::make_shared(), + std::make_shared(), constant, + std::make_shared(), + std::make_shared()}}, + {"FusedBatchNormV2", + {std::make_shared(), + std::make_shared(), constant, + std::make_shared(), + std::make_shared(), + std::make_shared()}}, + {"FusedBatchNormV3", + {std::make_shared(), + std::make_shared(), constant, + std::make_shared(), + std::make_shared(), + std::make_shared()}}, + {"FusedBatchNormGrad", + {constant, std::make_shared(), + std::make_shared(), + std::make_shared()}}, + {"FusedBatchNormGradV3", + {constant, std::make_shared(), + std::make_shared(), + std::make_shared()}}, + {"GatherNd", {std::make_shared()}}, + {"GatherV2", {std::make_shared()}}, + {"_FusedConv2D", + {std::make_shared(), + std::make_shared(), constant, + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared()}}, + {"_FusedMatMul", + {std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), constant, + std::make_shared(), + std::make_shared()}}, + {"Greater", {std::make_shared()}}, + {"GreaterEqual", {std::make_shared()}}, + {"Identity", {}}, {"IsFinite", + {constant, std::make_shared(), + std::make_shared(), + std::make_shared()}}, + {"L2Loss", + {constant, std::make_shared(), + std::make_shared(), + std::make_shared()}}, + {"LogSoftmax", + {std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), constant}}, + {"Less", {std::make_shared()}}, + {"LessEqual", {std::make_shared()}}, + {"Log", {std::make_shared()}}, + {"LogicalAnd", {std::make_shared()}}, + {"LogicalNot", {std::make_shared()}}, + {"LogicalOr", {std::make_shared()}}, + {"MatMul", + {std::make_shared(), + std::make_shared()}}, + {"Max", {std::make_shared(), constant}}, + {"Maximum", + {std::make_shared(), + std::make_shared()}}, + {"MaxPool", + {std::make_shared(), + std::make_shared()}}, + {"MaxPool3D", + {std::make_shared(), + std::make_shared()}}, + {"MaxPoolGrad", + {std::make_shared(), + std::make_shared()}}, + {"Mean", + {std::make_shared(), constant, + std::make_shared(), + std::make_shared()}}, + {"Min", {std::make_shared(), constant}}, + {"Minimum", + {std::make_shared(), + std::make_shared()}}, + {"Mul", {std::make_shared()}}, + {"Neg", {std::make_shared()}}, + {"OneHot", + {std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared()}}, + {"Pack", + {std::make_shared(), + std::make_shared()}}, + {"Pad", {constant, std::make_shared()}}, + {"Pow", {std::make_shared()}}, + {"PreventGradient", {}}, + {"Prod", + {std::make_shared(), constant, + std::make_shared()}}, + {"QuantizeAndDequantizeV2", + {constant, std::make_shared(), + std::make_shared()}}, + // Next few are CPU only ops + {"QuantizedAvgPool", + {std::make_shared(), + std::make_shared()}}, + {"QuantizedConcat", + {constant, std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared()}}, + {"QuantizedConcatV2", + {constant, std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared()}}, + {"QuantizedConv2DWithBiasAndReluAndRequantize", + {constant, std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared()}}, + {"QuantizedConv2DWithBiasAndRequantize", + {constant, std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared()}}, + {"QuantizedConv2DWithBiasSignedSumAndReluAndRequantize", + {constant, std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared()}}, + {"QuantizedConv2DWithBiasSumAndReluAndRequantize", + {constant, std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared()}}, + {"QuantizedMaxPool", + {std::make_shared(), + std::make_shared()}}, + // End of CPU only ops + {"QuantizeV2", + {constant, std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared()}}, + { + "RandomUniform", + {constant, std::make_shared()}, + }, + {"Rank", {constant}}, {"RealDiv", + {std::make_shared(), + std::make_shared()}}, + {"Reciprocal", {constant, std::make_shared()}}, + {"Relu", {std::make_shared()}}, + {"Relu6", + {constant, std::make_shared(), + std::make_shared()}}, + {"ReluGrad", {relu}}, + // TODO: remove Convert later + {"ResizeBilinear", + {std::make_shared(), + std::make_shared()}}, + {"Rsqrt", {constant, std::make_shared()}}, + {"RsqrtGrad", + {constant, std::make_shared(), + std::make_shared()}}, + {"Select", + {std::make_shared(), + std::make_shared(), + std::make_shared()}}, + {"Reshape", {std::make_shared()}}, + {"ScatterNd", {constant, std::make_shared()}}, + {"Shape", {constant}}, {"Sigmoid", + {constant, std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared()}}, + {"SigmoidGrad", + {constant, std::make_shared(), + std::make_shared()}}, + {"Sin", {std::make_shared()}}, {"Size", {constant}}, + {"Sign", {std::make_shared()}}, + {"Slice", {std::make_shared()}}, {"Snapshot", {}}, + {"Softmax", {std::make_shared(), constant}}, + {"SoftmaxCrossEntropyWithLogits", + {std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), constant}}, + {"Softplus", + {constant, std::make_shared(), + std::make_shared(), + std::make_shared()}}, + {"SpaceToDepth", + {std::make_shared(), + std::make_shared()}}, + {"SparseSoftmaxCrossEntropyWithLogits", + {std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), + std::make_shared(), constant}}, + {"Split", {std::make_shared()}}, + {"SplitV", {std::make_shared()}}, + {"Sqrt", {std::make_shared()}}, + {"Square", {std::make_shared()}}, + {"SquaredDifference", + {std::make_shared(), + std::make_shared(), + std::make_shared()}}, + {"Squeeze", {std::make_shared()}}, + {"StridedSlice", + {std::make_shared(), + std::make_shared(), + std::make_shared()}}, + {"Sub", {std::make_shared()}}, + {"Sum", + {std::make_shared(), + std::make_shared(), constant}}, + {"Tanh", {std::make_shared()}}, + {"TanhGrad", + {constant, std::make_shared(), + std::make_shared()}}, + {"Tile", {constant, std::make_shared()}}, + {"TopKV2", + {std::make_shared(), + std::make_shared()}}, + {"Transpose", {constant, std::make_shared()}}, + {"UnsortedSegmentSum", + {constant, std::make_shared()}}, + {"Unpack", + {std::make_shared(), + std::make_shared()}}, + {"ZerosLike", {constant}}, +#if defined NGRAPH_DISTRIBUTED + {"HorovodAllreduce", {std::make_shared()}}, + {"HorovodBroadcast", + {std::make_shared()}}, +#endif + {"NoOp", {}}, }; - mutex init_mu; - static bool initialized = false; + return TFtoNgraphOpMap; +} + +// +// Main entry point for the marking pass. +// +Status MarkForClustering(Graph* graph, const std::set skip_these_nodes, + const string& current_backend) { + const TypeConstraintMap& type_constraint_map = GetTypeConstraintMap(); + + // confirmation_function_map is non-const unlike the other maps + static std::map confirmation_function_map = + GetConfirmationMap(); + + const std::map& set_attributes_map = + GetAttributeSetters(); + + const std::map>>& + TFtoNgraphOpMap = GetTFToNgOpMap(); - // If the type constraint and confirmation function maps have not been - // initialized, initialize them. // // IF YOU ARE ADDING A NEW OP IMPLEMENTATION, YOU MUST ADD A CONFIRMATION // FUNCTION, TYPE CONTRAINTS (IF ANY) AND STATIC INPUTS INDEXES (IF ANY) FOR @@ -586,466 +1104,16 @@ Status MarkForClustering(Graph* graph, const std::set skip_these_nodes, static std::set disabled_ops_set = {}; + static bool initialized = false; + std::set disabled_ops_set_current = config::GetDisabledOps(); bool op_set_support_has_changed = disabled_ops_set_current != disabled_ops_set; - { - mutex_lock l(init_mu); - - if (!initialized || op_set_support_has_changed) { - // - // Initialize confirmation function map. - // - // Please keep these in alphabetical order by op name. - // - confirmation_function_map["Abs"] = SimpleConfirmationFunction(); - confirmation_function_map["Add"] = SimpleConfirmationFunction(); - confirmation_function_map["AddN"] = SimpleConfirmationFunction(); - confirmation_function_map["AddV2"] = SimpleConfirmationFunction(); - confirmation_function_map["Any"] = SimpleConfirmationFunction(); - confirmation_function_map["All"] = SimpleConfirmationFunction(); - confirmation_function_map["ArgMax"] = SimpleConfirmationFunction(); - confirmation_function_map["ArgMin"] = SimpleConfirmationFunction(); - confirmation_function_map["AvgPool"] = SimpleConfirmationFunction(); - confirmation_function_map["AvgPoolGrad"] = SimpleConfirmationFunction(); - confirmation_function_map["BatchMatMul"] = SimpleConfirmationFunction(); - confirmation_function_map["BatchMatMulV2"] = SimpleConfirmationFunction(); - confirmation_function_map["BiasAdd"] = SimpleConfirmationFunction(); - confirmation_function_map["BiasAddGrad"] = SimpleConfirmationFunction(); - confirmation_function_map["Cast"] = SimpleConfirmationFunction(); - confirmation_function_map["ConcatV2"] = SimpleConfirmationFunction(); - confirmation_function_map["Const"] = SimpleConfirmationFunction(); - confirmation_function_map["Conv2D"] = SimpleConfirmationFunction(); - confirmation_function_map["Conv2DBackpropFilter"] = - SimpleConfirmationFunction(); - confirmation_function_map["Conv2DBackpropInput"] = - SimpleConfirmationFunction(); - confirmation_function_map["Conv3D"] = SimpleConfirmationFunction(); - confirmation_function_map["Cos"] = SimpleConfirmationFunction(); - confirmation_function_map["DepthwiseConv2dNative"] = - SimpleConfirmationFunction(); - confirmation_function_map["DepthToSpace"] = [](Node* n, bool* result) { - std::string tf_data_format; - TF_RETURN_IF_ERROR( - GetNodeAttr(n->attrs(), "data_format", &tf_data_format)); - *result = tf_data_format != "NCHW_VECT_C"; - return Status::OK(); - }; - confirmation_function_map["Dequantize"] = [](Node* n, bool* result) { - string mode; - TF_RETURN_IF_ERROR(GetNodeAttr(n->attrs(), "mode", &mode)); - *result = (mode.compare("SCALED") == 0); - return Status::OK(); - }; - confirmation_function_map["Equal"] = SimpleConfirmationFunction(); - confirmation_function_map["Exp"] = SimpleConfirmationFunction(); - confirmation_function_map["ExpandDims"] = SimpleConfirmationFunction(); - confirmation_function_map["Fill"] = SimpleConfirmationFunction(); - confirmation_function_map["Floor"] = SimpleConfirmationFunction(); - confirmation_function_map["FloorDiv"] = SimpleConfirmationFunction(); - confirmation_function_map["FloorMod"] = SimpleConfirmationFunction(); - confirmation_function_map["FusedBatchNorm"] = - SimpleConfirmationFunction(); - confirmation_function_map["FusedBatchNormV2"] = - SimpleConfirmationFunction(); - confirmation_function_map["FusedBatchNormV3"] = - SimpleConfirmationFunction(); - confirmation_function_map["FusedBatchNormGrad"] = [](Node* n, - bool* result) { - TF_RETURN_IF_ERROR(GetNodeAttr(n->attrs(), "is_training", result)); - return Status::OK(); - }; - confirmation_function_map["FusedBatchNormGradV3"] = [](Node* n, - bool* result) { - TF_RETURN_IF_ERROR(GetNodeAttr(n->attrs(), "is_training", result)); - return Status::OK(); - }; - confirmation_function_map["_FusedConv2D"] = SimpleConfirmationFunction(); - confirmation_function_map["GatherNd"] = SimpleConfirmationFunction(); - confirmation_function_map["GatherV2"] = SimpleConfirmationFunction(); - confirmation_function_map["_FusedMatMul"] = - SimpleConfirmationFunction(); // TODO accept under all conditions? - // check? - confirmation_function_map["Greater"] = SimpleConfirmationFunction(); - confirmation_function_map["GreaterEqual"] = SimpleConfirmationFunction(); -#if defined NGRAPH_DISTRIBUTED - confirmation_function_map["HorovodAllreduce"] = - SimpleConfirmationFunction(); - confirmation_function_map["HorovodBroadcast"] = - SimpleConfirmationFunction(); -#endif - confirmation_function_map["Identity"] = SimpleConfirmationFunction(); - confirmation_function_map["IsFinite"] = SimpleConfirmationFunction(); - confirmation_function_map["L2Loss"] = SimpleConfirmationFunction(); - confirmation_function_map["LogSoftmax"] = SimpleConfirmationFunction(); - confirmation_function_map["Less"] = SimpleConfirmationFunction(); - confirmation_function_map["LessEqual"] = SimpleConfirmationFunction(); - confirmation_function_map["Log"] = SimpleConfirmationFunction(); - confirmation_function_map["LogicalAnd"] = SimpleConfirmationFunction(); - confirmation_function_map["LogicalNot"] = SimpleConfirmationFunction(); - confirmation_function_map["LogicalOr"] = SimpleConfirmationFunction(); - confirmation_function_map["MatMul"] = SimpleConfirmationFunction(); - confirmation_function_map["Max"] = SimpleConfirmationFunction(); - confirmation_function_map["Maximum"] = SimpleConfirmationFunction(); - confirmation_function_map["MaxPool"] = SimpleConfirmationFunction(); - confirmation_function_map["MaxPool3D"] = SimpleConfirmationFunction(); - confirmation_function_map["MaxPoolGrad"] = SimpleConfirmationFunction(); - confirmation_function_map["Mean"] = SimpleConfirmationFunction(); - confirmation_function_map["Min"] = SimpleConfirmationFunction(); - confirmation_function_map["Minimum"] = SimpleConfirmationFunction(); - confirmation_function_map["Mul"] = SimpleConfirmationFunction(); - confirmation_function_map["Neg"] = SimpleConfirmationFunction(); - confirmation_function_map["NoOp"] = SimpleConfirmationFunction(); - confirmation_function_map["OneHot"] = SimpleConfirmationFunction(); - confirmation_function_map["Pad"] = SimpleConfirmationFunction(); - confirmation_function_map["Pow"] = SimpleConfirmationFunction(); - confirmation_function_map["PreventGradient"] = - SimpleConfirmationFunction(); - confirmation_function_map["Prod"] = SimpleConfirmationFunction(); - confirmation_function_map["Rank"] = SimpleConfirmationFunction(); - confirmation_function_map["RandomUniform"] = SimpleConfirmationFunction(); - confirmation_function_map["QuantizeAndDequantizeV2"] = [](Node* n, - bool* result) { - // accept only when num_bits == 8 and range is given - bool range_given; - TF_RETURN_IF_ERROR( - GetNodeAttr(n->attrs(), "range_given", &range_given)); - int num_bits; - TF_RETURN_IF_ERROR(GetNodeAttr(n->attrs(), "num_bits", &num_bits)); - *result = (num_bits == 8) && range_given; - return Status::OK(); - }; - confirmation_function_map["QuantizedAvgPool"] = - SimpleConfirmationFunction(); - confirmation_function_map["QuantizedConcat"] = - SimpleConfirmationFunction(); - confirmation_function_map["QuantizedConcatV2"] = - SimpleConfirmationFunction(); - confirmation_function_map["QuantizedConv2DWithBiasAndReluAndRequantize"] = - SimpleConfirmationFunction(); - confirmation_function_map["QuantizedConv2DWithBiasAndRequantize"] = - SimpleConfirmationFunction(); - confirmation_function_map - ["QuantizedConv2DWithBiasSignedSumAndReluAndRequantize"] = - SimpleConfirmationFunction(); - confirmation_function_map - ["QuantizedConv2DWithBiasSumAndReluAndRequantize"] = - SimpleConfirmationFunction(); - confirmation_function_map["QuantizedMaxPool"] = - SimpleConfirmationFunction(); - confirmation_function_map["QuantizeV2"] = [](Node* n, bool* result) { - string mode; - TF_RETURN_IF_ERROR(GetNodeAttr(n->attrs(), "mode", &mode)); - *result = (mode.compare("SCALED") == 0); - return Status::OK(); - }; - confirmation_function_map["RealDiv"] = SimpleConfirmationFunction(); - confirmation_function_map["Reciprocal"] = SimpleConfirmationFunction(); - confirmation_function_map["Relu"] = SimpleConfirmationFunction(); - confirmation_function_map["Relu6"] = SimpleConfirmationFunction(); - confirmation_function_map["ReluGrad"] = SimpleConfirmationFunction(); - confirmation_function_map["Reshape"] = SimpleConfirmationFunction(); - confirmation_function_map["Rsqrt"] = SimpleConfirmationFunction(); - confirmation_function_map["RsqrtGrad"] = SimpleConfirmationFunction(); - confirmation_function_map["Select"] = SimpleConfirmationFunction(); - confirmation_function_map["Shape"] = SimpleConfirmationFunction(); - confirmation_function_map["Sigmoid"] = SimpleConfirmationFunction(); - confirmation_function_map["SigmoidGrad"] = SimpleConfirmationFunction(); - confirmation_function_map["Sign"] = SimpleConfirmationFunction(); - confirmation_function_map["Sin"] = SimpleConfirmationFunction(); - confirmation_function_map["Size"] = SimpleConfirmationFunction(); - confirmation_function_map["Slice"] = SimpleConfirmationFunction(); - confirmation_function_map["Snapshot"] = SimpleConfirmationFunction(); - confirmation_function_map["Softmax"] = SimpleConfirmationFunction(); - confirmation_function_map["SoftmaxCrossEntropyWithLogits"] = - SimpleConfirmationFunction(); - confirmation_function_map["Softplus"] = SimpleConfirmationFunction(); - confirmation_function_map["SpaceToDepth"] = - confirmation_function_map["DepthToSpace"]; - confirmation_function_map["SparseSoftmaxCrossEntropyWithLogits"] = - SimpleConfirmationFunction(); - confirmation_function_map["Split"] = SimpleConfirmationFunction(); - confirmation_function_map["SplitV"] = SimpleConfirmationFunction(); - confirmation_function_map["Sqrt"] = SimpleConfirmationFunction(); - confirmation_function_map["Square"] = SimpleConfirmationFunction(); - confirmation_function_map["SquaredDifference"] = - SimpleConfirmationFunction(); - confirmation_function_map["Squeeze"] = SimpleConfirmationFunction(); - confirmation_function_map["StridedSlice"] = SimpleConfirmationFunction(); - confirmation_function_map["Pack"] = SimpleConfirmationFunction(); - confirmation_function_map["Sub"] = SimpleConfirmationFunction(); - confirmation_function_map["Sum"] = SimpleConfirmationFunction(); - confirmation_function_map["Tanh"] = SimpleConfirmationFunction(); - confirmation_function_map["TanhGrad"] = SimpleConfirmationFunction(); - confirmation_function_map["Tile"] = SimpleConfirmationFunction(); - confirmation_function_map["TopKV2"] = [](Node* n, bool* result) { - bool sorted = true; - TF_RETURN_IF_ERROR(GetNodeAttr(n->attrs(), "sorted", &sorted)); - - // sorted = false is not supported right now, it falls back to TF if set - // to false. - *result = sorted; - return Status::OK(); - }; - confirmation_function_map["Transpose"] = SimpleConfirmationFunction(); - confirmation_function_map["Unpack"] = SimpleConfirmationFunction(); - confirmation_function_map["UnsortedSegmentSum"] = - SimpleConfirmationFunction(); - confirmation_function_map["ZerosLike"] = SimpleConfirmationFunction(); - - // - // Initialize type constraint map. - // - type_constraint_map["Abs"]["T"] = NGraphNumericDTypes(); - type_constraint_map["Add"]["T"] = NGraphNumericDTypes(); - type_constraint_map["AddN"]["T"] = NGraphNumericDTypes(); - type_constraint_map["AddV2"]["T"] = NGraphNumericDTypes(); - type_constraint_map["Any"]["Tidx"] = NGraphIndexDTypes(); - type_constraint_map["All"]["Tidx"] = NGraphIndexDTypes(); - type_constraint_map["ArgMax"]["T"] = NGraphNumericDTypes(); - type_constraint_map["ArgMax"]["Tidx"] = NGraphIndexDTypes(); - type_constraint_map["ArgMin"]["T"] = NGraphNumericDTypes(); - type_constraint_map["ArgMin"]["Tidx"] = NGraphIndexDTypes(); - type_constraint_map["AvgPool"]["T"] = NGraphNumericDTypes(); - type_constraint_map["AvgPoolGrad"]["T"] = NGraphNumericDTypes(); - type_constraint_map["BatchMatMul"]["T"] = NGraphNumericDTypes(); - type_constraint_map["BatchMatMulV2"]["T"] = NGraphNumericDTypes(); - type_constraint_map["BiasAdd"]["T"] = NGraphNumericDTypes(); - type_constraint_map["BiasAddGrad"]["T"] = NGraphNumericDTypes(); - type_constraint_map["Cast"]["SrcT"] = NGraphDTypes(); - type_constraint_map["Cast"]["DstT"] = NGraphDTypes(); - type_constraint_map["ConcatV2"]["T"] = NGraphDTypes(); - type_constraint_map["ConcatV2"]["Tidx"] = NGraphIndexDTypes(); - type_constraint_map["Const"]["dtype"] = NGraphDTypes(); - type_constraint_map["Conv2D"]["T"] = NGraphNumericDTypes(); - type_constraint_map["Conv2DBackpropInput"]["T"] = NGraphNumericDTypes(); - type_constraint_map["Conv3D"]["T"] = NGraphNumericDTypes(); - type_constraint_map["Cos"]["T"] = NGraphRealDTypes(); - type_constraint_map["DepthToSpace"]["T"] = NGraphDTypes(); - type_constraint_map["DepthwiseConv2dNative"]["T"] = NGraphNumericDTypes(); - type_constraint_map["Dequantize"]["T"] = NGraphSupportedQuantizedDTypes(); - type_constraint_map["Equal"]["T"] = NGraphDTypes(); - type_constraint_map["Exp"]["T"] = NGraphNumericDTypes(); - type_constraint_map["ExpandDims"]["T"] = NGraphDTypes(); - type_constraint_map["Floor"]["T"] = NGraphNumericDTypes(); - type_constraint_map["FloorDiv"]["T"] = NGraphNumericDTypes(); - type_constraint_map["FloorMod"]["T"] = NGraphNumericDTypes(); - type_constraint_map["FusedBatchNorm"]["T"] = NGraphNumericDTypes(); - // TODO (mingshan): FusedBatchNormV2, V3 supports DT_HALF,DT_BFLOAT16, - // DT_FLOAT - type_constraint_map["FusedBatchNormV2"]["T"] = {DT_FLOAT}; - type_constraint_map["FusedBatchNormV3"]["T"] = {DT_FLOAT}; - type_constraint_map["FusedBatchNormGrad"]["T"] = NGraphNumericDTypes(); - type_constraint_map["GatherNd"]["Tparams"] = { - DT_FLOAT}; // NGraphDTypes(); - type_constraint_map["GatherNd"]["Tindices"] = NGraphIndexDTypes(); - type_constraint_map["FusedBatchNormGradV3"]["T"] = NGraphNumericDTypes(); - type_constraint_map["GatherV2"]["Tparams"] = NGraphDTypes(); - type_constraint_map["GatherV2"]["Tindices"] = NGraphIndexDTypes(); - type_constraint_map["GatherV2"]["Taxis"] = NGraphIndexDTypes(); - type_constraint_map["_FusedConv2D"]["T"] = NGraphRealDTypes(); - type_constraint_map["_FusedMatMul"]["T"] = NGraphRealDTypes(); - type_constraint_map["Greater"]["T"] = NGraphDTypes(); - type_constraint_map["GreaterEqual"]["T"] = NGraphDTypes(); -#if defined NGRAPH_DISTRIBUTED - type_constraint_map["HorovodAllreduce"]["T"] = NGraphNumericDTypes(); - type_constraint_map["HorovodBroadcast"]["T"] = NGraphNumericDTypes(); -#endif - type_constraint_map["Identity"]["T"] = NGraphDTypes(); - type_constraint_map["IsFinite"]["T"] = NGraphRealDTypes(); - type_constraint_map["L2Loss"]["T"] = NGraphNumericDTypes(); - type_constraint_map["LogSoftmax"]["T"] = NGraphRealDTypes(); - type_constraint_map["Less"]["T"] = NGraphDTypes(); - type_constraint_map["LessEqual"]["T"] = NGraphDTypes(); - type_constraint_map["Log"]["T"] = NGraphNumericDTypes(); - // LogicalAnd and LogicalNot have no type attributes ("T", if it existed, - // would always be bool). - type_constraint_map["MatMul"]["T"] = NGraphNumericDTypes(); - type_constraint_map["Max"]["T"] = NGraphNumericDTypes(); - type_constraint_map["Max"]["Tidx"] = NGraphIndexDTypes(); - type_constraint_map["Maximum"]["T"] = NGraphNumericDTypes(); - type_constraint_map["MaxPool"]["T"] = NGraphNumericDTypes(); - type_constraint_map["MaxPool3D"]["T"] = NGraphNumericDTypes(); - type_constraint_map["MaxPoolGrad"]["T"] = NGraphNumericDTypes(); - type_constraint_map["Mean"]["T"] = NGraphNumericDTypes(); - type_constraint_map["Mean"]["Tidx"] = NGraphIndexDTypes(); - type_constraint_map["Min"]["T"] = NGraphNumericDTypes(); - type_constraint_map["Min"]["Tidx"] = NGraphIndexDTypes(); - type_constraint_map["Minimum"]["T"] = NGraphNumericDTypes(); - type_constraint_map["Mul"]["T"] = NGraphNumericDTypes(); - type_constraint_map["Neg"]["T"] = NGraphNumericDTypes(); - type_constraint_map["NonMaxSuppressionV4"]["T"] = { - DT_FLOAT}; // TF allows half too - type_constraint_map["OneHot"]["T"] = NGraphDTypes(); - type_constraint_map["Pack"]["T"] = NGraphDTypes(); - type_constraint_map["RandomUniform"]["T"] = NGraphDTypes(); - type_constraint_map["Pad"]["T"] = NGraphDTypes(); - type_constraint_map["Pad"]["Tpaddings"] = NGraphIndexDTypes(); - type_constraint_map["Pow"]["T"] = NGraphNumericDTypes(); - type_constraint_map["PreventGradient"]["T"] = NGraphDTypes(); - type_constraint_map["Prod"]["T"] = NGraphNumericDTypes(); - type_constraint_map["Prod"]["Tidx"] = NGraphIndexDTypes(); - type_constraint_map["QuantizeAndDequantizeV2"]["T"] = NGraphRealDTypes(); - type_constraint_map["QuantizedAvgPool"]["T"] = - NGraphSupportedQuantizedDTypes(); - type_constraint_map["QuantizedConcat"]["T"] = - NGraphSupportedQuantizedDTypes(); - type_constraint_map["QuantizedConcatV2"]["T"] = - NGraphSupportedQuantizedDTypes(); - type_constraint_map["QuantizedConv2DWithBiasAndReluAndRequantize"] - ["Tinput"] = NGraphSupportedQuantizedDTypes(); - type_constraint_map["QuantizedConv2DWithBiasAndReluAndRequantize"] - ["Tfilter"] = NGraphSupportedQuantizedDTypes(); - type_constraint_map["QuantizedConv2DWithBiasAndReluAndRequantize"] - ["Tbias"] = NGraphBiasDTypes(); - // TODO: check if any other type constraint is required - // https://github.com/tensorflow/tensorflow/blob/c95ca05536144451ef78ca6e2c15f0f65ebaaf95/tensorflow/core/ops/nn_ops.cc#L2780 - type_constraint_map - ["QuantizedConv2DWithBiasSignedSumAndReluAndRequantize"]["Tinput"] = - NGraphSupportedQuantizedDTypes(); - type_constraint_map - ["QuantizedConv2DWithBiasSignedSumAndReluAndRequantize"]["Tsummand"] = - NGraphSupportedQuantizedDTypes(); - type_constraint_map - ["QuantizedConv2DWithBiasSignedSumAndReluAndRequantize"]["Tfilter"] = - NGraphSupportedQuantizedDTypes(); - type_constraint_map - ["QuantizedConv2DWithBiasSignedSumAndReluAndRequantize"]["Tbias"] = - NGraphBiasDTypes(); - type_constraint_map["QuantizedConv2DWithBiasSumAndReluAndRequantize"] - ["Tinput"] = NGraphSupportedQuantizedDTypes(); - type_constraint_map["QuantizedConv2DWithBiasSumAndReluAndRequantize"] - ["Tsummand"] = NGraphSupportedQuantizedDTypes(); - type_constraint_map["QuantizedConv2DWithBiasSumAndReluAndRequantize"] - ["Tfilter"] = NGraphSupportedQuantizedDTypes(); - type_constraint_map["QuantizedConv2DWithBiasSumAndReluAndRequantize"] - ["Tbias"] = NGraphBiasDTypes(); - type_constraint_map["QuantizedConv2DWithBiasAndRequantize"]["Tinput"] = - NGraphSupportedQuantizedDTypes(); - type_constraint_map["QuantizedConv2DWithBiasAndRequantize"]["Tfilter"] = - NGraphSupportedQuantizedDTypes(); - type_constraint_map["QuantizedConv2DWithBiasAndRequantize"]["Tbias"] = - NGraphBiasDTypes(); - type_constraint_map["QuantizedMaxPool"]["T"] = - NGraphSupportedQuantizedDTypes(); - type_constraint_map["QuantizeV2"]["T"] = NGraphSupportedQuantizedDTypes(); - type_constraint_map["Rank"]["T"] = NGraphNumericDTypes(); - type_constraint_map["RealDiv"]["T"] = NGraphNumericDTypes(); - type_constraint_map["Reciprocal"]["T"] = NGraphNumericDTypes(); - type_constraint_map["Relu"]["T"] = NGraphNumericDTypes(); - type_constraint_map["Relu6"]["T"] = NGraphNumericDTypes(); - type_constraint_map["ReluGrad"]["T"] = NGraphNumericDTypes(); - type_constraint_map["Reshape"]["T"] = NGraphDTypes(); - type_constraint_map["Reshape"]["Tshape"] = NGraphIndexDTypes(); - type_constraint_map["Rsqrt"]["T"] = NGraphDTypes(); - type_constraint_map["RsqrtGrad"]["T"] = NGraphRealDTypes(); - type_constraint_map["Select"]["T"] = NGraphDTypes(); - type_constraint_map["Shape"]["T"] = NGraphDTypes(); - type_constraint_map["Shape"]["out_type"] = NGraphIndexDTypes(); - type_constraint_map["Sigmoid"]["T"] = NGraphNumericDTypes(); - type_constraint_map["SigmoidGrad"]["T"] = NGraphNumericDTypes(); - type_constraint_map["Sign"]["T"] = NGraphNumericDTypes(); - type_constraint_map["Sin"]["T"] = NGraphRealDTypes(); - type_constraint_map["Size"]["T"] = NGraphDTypes(); - type_constraint_map["Size"]["out_type"] = NGraphIndexDTypes(); - type_constraint_map["Slice"]["T"] = NGraphDTypes(); - type_constraint_map["Slice"]["Index"] = NGraphIndexDTypes(); - type_constraint_map["Snapshot"]["T"] = NGraphDTypes(); - type_constraint_map["Softmax"]["T"] = NGraphNumericDTypes(); - // For SoftmaxCrossEntropyWithLogits, see - // https://github.com/tensorflow/tensorflow/blob/c95ca05536144451ef78ca6e2c15f0f65ebaaf95/tensorflow/core/ops/nn_ops.cc#L1096 - type_constraint_map["SoftmaxCrossEntropyWithLogits"]["T"] = - NGraphRealDTypes(); - type_constraint_map["Softplus"]["T"] = NGraphRealDTypes(); - type_constraint_map["SpaceToDepth"]["T"] = NGraphDTypes(); - type_constraint_map["SparseSoftmaxCrossEntropyWithLogits"]["T"] = - NGraphRealDTypes(); - type_constraint_map["SparseSoftmaxCrossEntropyWithLogits"]["Tlabels"] = - NGraphNumericDTypes(); - type_constraint_map["Split"]["T"] = NGraphDTypes(); - type_constraint_map["SplitV"]["T"] = NGraphDTypes(); - type_constraint_map["SplitV"]["Tlen"] = NGraphIndexDTypes(); - type_constraint_map["Sqrt"]["T"] = NGraphDTypes(); - type_constraint_map["Square"]["T"] = NGraphDTypes(); - type_constraint_map["SquaredDifference"]["T"] = NGraphDTypes(); - type_constraint_map["Squeeze"]["T"] = NGraphDTypes(); - type_constraint_map["StridedSlice"]["T"] = NGraphDTypes(); - type_constraint_map["StridedSlice"]["Index"] = NGraphIndexDTypes(); - type_constraint_map["Sub"]["T"] = NGraphNumericDTypes(); - type_constraint_map["Sum"]["T"] = NGraphNumericDTypes(); - type_constraint_map["Sum"]["Tidx"] = NGraphIndexDTypes(); - type_constraint_map["Tanh"]["T"] = NGraphNumericDTypes(); - type_constraint_map["TanhGrad"]["T"] = NGraphNumericDTypes(); - type_constraint_map["Tile"]["T"] = NGraphNumericDTypes(); - type_constraint_map["Tile"]["Tmultiples"] = NGraphIndexDTypes(); - type_constraint_map["TopKV2"]["T"] = NGraphNumericDTypes(); - type_constraint_map["Transpose"]["T"] = NGraphDTypes(); - type_constraint_map["Transpose"]["Tperm"] = NGraphIndexDTypes(); - type_constraint_map["Unpack"]["T"] = NGraphDTypes(); - type_constraint_map["UnsortedSegmentSum"]["T"] = NGraphNumericDTypes(); - type_constraint_map["UnsortedSegmentSum"]["Tindices"] = - NGraphIndexDTypes(); - type_constraint_map["UnsortedSegmentSum"]["Tnumsegments"] = - NGraphIndexDTypes(); - - // Set Additional Attributes (if any) - set_attributes_map["Any"] = SetStaticInputs({1}); - set_attributes_map["All"] = SetStaticInputs({1}); - set_attributes_map["ArgMax"] = SetStaticInputs({1}); - set_attributes_map["ArgMin"] = SetStaticInputs({1}); - set_attributes_map["AvgPoolGrad"] = SetStaticInputs({0}); - set_attributes_map["ConcatV2"] = SetStaticInputs({-1}); - set_attributes_map["CombinedNonMaxSuppression"] = - SetStaticInputs({2, 3, 4, 5}); - set_attributes_map["Conv2DBackpropFilter"] = SetStaticInputs({1}); - set_attributes_map["Conv2DBackpropInput"] = SetStaticInputs({0}); - set_attributes_map["ExpandDims"] = SetStaticInputs({1}); - set_attributes_map["Fill"] = SetStaticInputs({0}); - set_attributes_map["GatherV2"] = SetStaticInputs({2}); - set_attributes_map["Max"] = SetStaticInputs({1}); - set_attributes_map["Mean"] = SetStaticInputs({1}); - set_attributes_map["Min"] = SetStaticInputs({1}); - set_attributes_map["NonMaxSuppressionV4"] = SetStaticInputs({2, 3, 4}); - set_attributes_map["OneHot"] = SetStaticInputs({1}); - set_attributes_map["Pad"] = SetStaticInputs({1}); - set_attributes_map["Prod"] = SetStaticInputs({1}); - - set_attributes_map["QuantizeAndDequantizeV2"] = SetStaticInputs({1, 2}); - set_attributes_map["QuantizedConcat"] = [](Node* n) { - SetStaticInputs(n, {0}); // the axis - auto num_of_tensors_to_concat = (n->num_inputs() - 1) / 3; - // mark all mins and maxes static - for (int idx = num_of_tensors_to_concat + 1; idx < n->num_inputs(); - idx++) { - SetStaticInputs(n, {idx}); - } - return Status::OK(); - }; - set_attributes_map["QuantizedConcatV2"] = [](Node* n) { - auto num_of_tensors_to_concat = (n->num_inputs() - 1) / 3; - // mark axis, all mins and maxes static - std::vector static_input_vec; - for (int idx = num_of_tensors_to_concat; idx < n->num_inputs(); idx++) { - static_input_vec.push_back(idx); - } - SetStaticInputs(n, static_input_vec); - return Status::OK(); - }; - set_attributes_map["RandomUniform"] = SetStaticInputs({0}); - set_attributes_map["Reshape"] = SetStaticInputs({1}); - set_attributes_map["Slice"] = SetStaticInputs({1, 2}); - set_attributes_map["Split"] = SetStaticInputs({0}); - set_attributes_map["SplitV"] = SetStaticInputs({1, 2}); - set_attributes_map["StridedSlice"] = SetStaticInputs({1, 2, 3}); - set_attributes_map["Sum"] = SetStaticInputs({1}); - set_attributes_map["TopKV2"] = SetStaticInputs({1}); - set_attributes_map["Tile"] = SetStaticInputs({1}); - set_attributes_map["Transpose"] = SetStaticInputs({1}); - set_attributes_map["UnsortedSegmentSum"] = SetStaticInputs({2}); - initialized = true; - } + if (!initialized || op_set_support_has_changed) { + confirmation_function_map = GetConfirmationMap(); + initialized = true; } // Right now it cannot be inside the if(!initialized) block, because it is @@ -1249,6 +1317,11 @@ void SetNodeBackend(Node* node, const string& backend_name) { node->AddAttr("_ngraph_backend", backend_name); } +void ResetMarkForClustering(Graph* graph) { + ClearAttribute(graph, {"_ngraph_marked_for_clustering", "_ngraph_backend", + "_ngraph_static_inputs"}); +} + } // namespace ngraph_bridge } // namespace tensorflow diff --git a/ngraph_bridge/ngraph_mark_for_clustering.h b/ngraph_bridge/ngraph_mark_for_clustering.h index 41a8d02a0..94872fde7 100644 --- a/ngraph_bridge/ngraph_mark_for_clustering.h +++ b/ngraph_bridge/ngraph_mark_for_clustering.h @@ -28,9 +28,11 @@ namespace ngraph_bridge { Status MarkForClustering(Graph* graph, std::set skip_these_nodes, const string& current_backend); +// remove marking, backend and static input nodes attributes +void ResetMarkForClustering(Graph* graph); Status IsSupportedByBackend( const Node* node, const ngraph::runtime::Backend* op_backend, - std::map>>& + const std::map>>& TFtoNgraphOpMap, bool& is_supported); bool NodeIsMarkedForClustering(const Node* node); @@ -38,6 +40,19 @@ void GetStaticInputs(const Node* node, std::vector* inputs); bool InputIsStatic(const Node* node, int index); Status GetNodeBackend(const Node* node, string* backend_name); void SetNodeBackend(Node* node, const string& backend_name); + +using SetAttributesFunction = std::function; +const std::map& GetAttributeSetters(); + +using TypeConstraintMap = + std::map>>; +const TypeConstraintMap& GetTypeConstraintMap(); + +using ConfirmationFunction = std::function; +const std::map& GetConfirmationMap(); + +const std::map>>& +GetTFToNgOpMap(); } // namespace ngraph_bridge } // namespace tensorflow diff --git a/ngraph_bridge/ngraph_rewrite_pass.cc b/ngraph_bridge/ngraph_rewrite_pass.cc index 4af428980..340001c28 100644 --- a/ngraph_bridge/ngraph_rewrite_pass.cc +++ b/ngraph_bridge/ngraph_rewrite_pass.cc @@ -230,8 +230,12 @@ class NGraphEncapsulationPass : public NGraphRewritePass { // 4. Encapsulate clusters then, if requested, dump the graphs. FunctionDefLibrary* fdeflib_new = new FunctionDefLibrary(); - TF_RETURN_IF_ERROR(EncapsulateClusters(options.graph->get(), idx, - fdeflib_new, config_map, {0, {}})); + auto status = EncapsulateClusters(options.graph->get(), idx, fdeflib_new, + config_map, {0, {}}); + if (status != Status::OK()) { + delete (fdeflib_new); + return status; + } // TODO: not using fdeflib_new in this path. Only grappler path uses it delete (fdeflib_new); if (DumpEncapsulatedGraphs()) { diff --git a/ngraph_bridge/ngraph_utils.cc b/ngraph_bridge/ngraph_utils.cc index e3cad7be8..4c0f69416 100644 --- a/ngraph_bridge/ngraph_utils.cc +++ b/ngraph_bridge/ngraph_utils.cc @@ -600,6 +600,15 @@ bool IsProcessedByNgraphPass(Graph* g) { return false; } +void ClearAttribute(Graph* g, + const std::set& attributes_to_be_cleared) { + for (auto node : g->nodes()) { + for (const auto& attr : attributes_to_be_cleared) { + node->ClearAttr(attr); + } + } +} + } // namespace ngraph_bridge } // namespace tensorflow diff --git a/ngraph_bridge/ngraph_utils.h b/ngraph_bridge/ngraph_utils.h index daa6cbf5b..84cd624de 100644 --- a/ngraph_bridge/ngraph_utils.h +++ b/ngraph_bridge/ngraph_utils.h @@ -140,32 +140,36 @@ Status ValuesFromConstNode(const NodeDef& node, n_elements *= shape.dim(i).size(); } values->resize(n_elements); + + auto val_lastsaved = (T)0; // cast + for (auto i = 0; i < n_elements; i++) { auto& tensor = node.attr().at("value").tensor(); auto dt = node.attr().at("dtype").type(); + int64 val_size = 0; + auto val_i = (T)0; // cast switch (dt) { // TODO(amprocte/NGRAPH-2502): there are more element types to support // here case DT_INT32: - (*values)[i] = (tensor.int_val_size() == 1 ? tensor.int_val()[0] - : tensor.int_val()[i]); + val_size = tensor.int_val_size(); + if (val_size > 0) val_i = tensor.int_val()[i]; break; case DT_INT64: - (*values)[i] = (tensor.int64_val_size() == 1 ? tensor.int64_val()[0] - : tensor.int64_val()[i]); + val_size = tensor.int64_val_size(); + if (val_size > 0) val_i = tensor.int64_val()[i]; break; case DT_FLOAT: - (*values)[i] = (tensor.float_val_size() == 1 ? tensor.float_val()[0] - : tensor.float_val()[i]); + val_size = tensor.float_val_size(); + if (val_size > 0) val_i = tensor.float_val()[i]; break; case DT_BOOL: - (*values)[i] = (tensor.bool_val_size() == 1 ? tensor.bool_val()[0] - : tensor.bool_val()[i]); + val_size = tensor.bool_val_size(); + if (val_size > 0) val_i = tensor.bool_val()[i]; break; case DT_DOUBLE: - (*values)[i] = - (tensor.double_val_size() == 1 ? tensor.double_val()[0] - : tensor.double_val()[i]); + val_size = tensor.double_val_size(); + if (val_size > 0) val_i = tensor.double_val()[i]; break; default: NGRAPH_VLOG(0) @@ -177,6 +181,14 @@ Status ValuesFromConstNode(const NodeDef& node, DataType_Name(dt), " on an empty tensor"); } + if (val_size == 0) { + return errors::InvalidArgument("Empty values vector"); + } else if (i < val_size) { + (*values)[i] = val_i; + val_lastsaved = val_i; + } else { + (*values)[i] = val_lastsaved; + } } } else { values->resize(tensor_content_size / sizeof(VecT)); @@ -336,6 +348,8 @@ std::string GraphFilenamePrefix(std::string, int); std::string GraphFilenamePrefix(std::string, int, int); +void ClearAttribute(Graph*, const std::set&); + void DumpGraphs(const GraphOptimizationPassOptions& options, int idx, std::string filename_prefix, std::string title); diff --git a/python/setup.in.py b/python/setup.in.py index 215628a1e..c87d36e88 100644 --- a/python/setup.in.py +++ b/python/setup.in.py @@ -59,7 +59,7 @@ def get_tag(self): setup( name='ngraph_tensorflow_bridge', - version='0.22.0rc1', + version='0.22.0rc2', description='Intel nGraph compiler and runtime for TensorFlow', long_description=long_description, long_description_content_type="text/markdown", diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7648216ed..8d47f9a7f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -56,6 +56,7 @@ set(SRC test_index_library.cpp test_ngraph_data_cache.cpp test_utilities.cpp + test_image_ops.cpp test_math_ops.cpp test_nn_ops.cpp test_array_ops.cpp @@ -68,6 +69,8 @@ set(SRC test_ngraph_tensor_manager.cpp test_capture_prefetch.cpp test_pipelined_tensor_store.cc + dummy_backend.cpp + test_dummy_backend.cpp ) if(NGRAPH_TF_ENABLE_VARIABLES_AND_OPTIMIZERS) @@ -137,6 +140,10 @@ if (APPLE) set(NGRAPH_TF_CXX11_ABI 0) endif() +if(NGRAPH_BRIDGE_STATIC_LIB_ENABLE) + add_definitions(-DNGRAPH_BRIDGE_STATIC_LIB_ENABLE) +endif() + if(NGRAPH_BRIDGE_STATIC_LIB_ENABLE) target_link_libraries(gtest_ngtf -Wl,--whole-archive diff --git a/test/dummy_backend.cpp b/test/dummy_backend.cpp new file mode 100644 index 000000000..901c5cf9d --- /dev/null +++ b/test/dummy_backend.cpp @@ -0,0 +1,75 @@ +//***************************************************************************** +// Copyright 2017-2020 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//***************************************************************************** + +#include "ngraph/descriptor/layout/dense_tensor_layout.hpp" +#include "ngraph/op/util/binary_elementwise_comparison.hpp" +#include "ngraph/pass/assign_layout.hpp" +#include "ngraph/pass/like_replacement.hpp" +#include "ngraph/pass/liveness.hpp" +#include "ngraph/pass/manager.hpp" +#include "ngraph/runtime/backend_manager.hpp" +#include "ngraph/util.hpp" + +#include "test/dummy_backend.h" + +using namespace std; +namespace ng = ngraph; + +namespace ngraph { + +using descriptor::layout::DenseTensorLayout; +runtime::dummy::DummyBackend::DummyBackend() {} + +shared_ptr runtime::dummy::DummyBackend::create_tensor( + const ng::element::Type& type, const ng::Shape& shape) { + return make_shared(type, shape, "external"); +} + +shared_ptr runtime::dummy::DummyBackend::create_tensor( + const ng::element::Type& type, const ng::Shape& shape, + void* memory_pointer) { + return make_shared(type, shape, memory_pointer, + "external"); +} + +shared_ptr runtime::dummy::DummyBackend::compile( + shared_ptr function, bool enable_performance_collection) { + return make_shared(function, enable_performance_collection); +} + +bool runtime::dummy::DummyBackend::is_supported(const Node& node) const { + return false; +} + +runtime::dummy::DummyBackend::~DummyBackend() {} + +runtime::dummy::DummyExecutable::DummyExecutable( + shared_ptr function, + bool /* enable_performance_collection */) { + pass::Manager pass_manager; + pass_manager.register_pass>(); + pass_manager.run_passes(function); + + set_parameters_and_results(*function); +} + +bool runtime::dummy::DummyExecutable::call( + const vector>& /* outputs */, + const vector>& /* inputs */) { + return true; +} + +} // namespace ngraph diff --git a/test/dummy_backend.h b/test/dummy_backend.h new file mode 100644 index 000000000..1e6218d25 --- /dev/null +++ b/test/dummy_backend.h @@ -0,0 +1,76 @@ +//***************************************************************************** +// Copyright 2017-2020 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//***************************************************************************** +#ifndef NGRAPH_TF_BRIDGE_DUMMYBACKEND_H_ +#define NGRAPH_TF_BRIDGE_DUMMYBACKEND_H_ + +#pragma once + +#include +#include +#include +#include + +#include "ngraph/runtime/backend.hpp" +#include "ngraph/runtime/host_tensor.hpp" +#include "ngraph/runtime/tensor.hpp" + +using namespace std; +namespace ng = ngraph; + +namespace ngraph { + +namespace runtime { + +namespace dummy { + +class DummyBackend; +class DummyExecutable; +} +} +} + +class ng::runtime::dummy::DummyBackend : public ng::runtime::Backend { + public: + DummyBackend(); + DummyBackend(const DummyBackend&) = delete; + DummyBackend(DummyBackend&&) = delete; + DummyBackend& operator=(const DummyBackend&) = delete; + + std::shared_ptr create_tensor( + const ng::element::Type& type, const ng::Shape& shape, + void* memory_pointer) override; + + std::shared_ptr create_tensor( + const ng::element::Type& type, const ng::Shape& shape) override; + + std::shared_ptr compile( + std::shared_ptr function, + bool enable_performance_data = false) override; + + bool is_supported(const ngraph::Node& node) const override; + ~DummyBackend() override; +}; + +class ng::runtime::dummy::DummyExecutable : public ng::runtime::Executable { + public: + DummyExecutable(std::shared_ptr function, + bool enable_performance_collection = false); + bool call( + const std::vector>& outputs, + const std::vector>& inputs) override; +}; + +#endif // NGRAPH_TF_BRIDGE_DUMMYBACKEND_H_ \ No newline at end of file diff --git a/test/graph_rewrites/assign_clusters.cc b/test/graph_rewrites/assign_clusters.cc index 0eb010c2e..02bfb6b17 100644 --- a/test/graph_rewrites/assign_clusters.cc +++ b/test/graph_rewrites/assign_clusters.cc @@ -103,6 +103,7 @@ TEST(AssignClusters, ConstToStatic) { // Node1-->Node2 coalesced // Node1-->Node3 coalesced **actually invalid, because Node1 is now in same // cluster as Node2, and we can't contract 2 & 3. +// Also tests ResetAssignClusters TEST(AssignClusters, Cone) { Graph g(OpRegistry::Global()); @@ -147,11 +148,24 @@ TEST(AssignClusters, Cone) { ASSERT_OK(AssignClusters(&g)); - int node2_cluster, node3_cluster; + int node1_cluster, node2_cluster, node3_cluster; + ASSERT_OK(GetNodeCluster(node1, &node1_cluster)); ASSERT_OK(GetNodeCluster(node2, &node2_cluster)); ASSERT_OK(GetNodeCluster(node3, &node3_cluster)); ASSERT_NE(node2_cluster, node3_cluster); + ASSERT_EQ(node1_cluster, node2_cluster); + + ResetAssignClusters(&g); + // After the reset function the attribute should have disappeared, and using + // GetNodeCluster should return -1 + ASSERT_NOT_OK(GetNodeCluster(node1, &node1_cluster)); + ASSERT_NOT_OK(GetNodeCluster(node2, &node2_cluster)); + ASSERT_NOT_OK(GetNodeCluster(node3, &node3_cluster)); + + ASSERT_EQ(node1_cluster, -1); + ASSERT_EQ(node2_cluster, -1); + ASSERT_EQ(node3_cluster, -1); } } // namespace testing diff --git a/test/graph_rewrites/disable_ops_test.cc b/test/graph_rewrites/disable_ops_test.cc index 568dc6d59..434dc20aa 100644 --- a/test/graph_rewrites/disable_ops_test.cc +++ b/test/graph_rewrites/disable_ops_test.cc @@ -114,9 +114,7 @@ TEST(DisableOps, DisableTest) { GetNodeAttr(node3->attrs(), "_ngraph_marked_for_clustering", &marked)); ASSERT_TRUE(marked); - node1->ClearAttr("_ngraph_marked_for_clustering"); - node2->ClearAttr("_ngraph_marked_for_clustering"); - node3->ClearAttr("_ngraph_marked_for_clustering"); + ResetMarkForClustering(&g); // Add is disabled config::ngraph_set_disabled_ops("Add,Mul"); @@ -132,9 +130,7 @@ TEST(DisableOps, DisableTest) { ASSERT_NOT_OK( GetNodeAttr(node3->attrs(), "_ngraph_marked_for_clustering", &marked)); - node1->ClearAttr("_ngraph_marked_for_clustering"); - node2->ClearAttr("_ngraph_marked_for_clustering"); - node3->ClearAttr("_ngraph_marked_for_clustering"); + ResetMarkForClustering(&g); // Add,Add,Mul,Add should work too config::ngraph_set_disabled_ops("Add,Add,Mul,Add"); @@ -150,9 +146,7 @@ TEST(DisableOps, DisableTest) { ASSERT_NOT_OK( GetNodeAttr(node3->attrs(), "_ngraph_marked_for_clustering", &marked)); - node1->ClearAttr("_ngraph_marked_for_clustering"); - node2->ClearAttr("_ngraph_marked_for_clustering"); - node3->ClearAttr("_ngraph_marked_for_clustering"); + ResetMarkForClustering(&g); // Resetting it. So Add should be accepted now config::ngraph_set_disabled_ops(""); @@ -169,9 +163,7 @@ TEST(DisableOps, DisableTest) { GetNodeAttr(node3->attrs(), "_ngraph_marked_for_clustering", &marked)); ASSERT_TRUE(marked); - node1->ClearAttr("_ngraph_marked_for_clustering"); - node2->ClearAttr("_ngraph_marked_for_clustering"); - node3->ClearAttr("_ngraph_marked_for_clustering"); + ResetMarkForClustering(&g); // Invalid op name should trigger an error config::ngraph_set_disabled_ops("Add,_InvalidOp"); diff --git a/test/graph_rewrites/mark_for_clustering_test.cc b/test/graph_rewrites/mark_for_clustering_test.cc index 2ae15c294..418230cba 100644 --- a/test/graph_rewrites/mark_for_clustering_test.cc +++ b/test/graph_rewrites/mark_for_clustering_test.cc @@ -58,6 +58,12 @@ TEST(MarkForClustering, SimpleTest) { .Attr("T", DT_FLOAT) .Finalize(&g, &node3)); + Node* node4; + ASSERT_OK(NodeBuilder("node4", "Abs") + .Input(node3, 0) + .Attr("T", DT_FLOAT) + .Finalize(&g, &node4)); + // Add edges from SRC to node1 and node2 // Add edge from node3 to SINK // The graph is disconnected without these edges @@ -65,7 +71,7 @@ TEST(MarkForClustering, SimpleTest) { Node* sink = g.sink_node(); g.AddEdge(source, Graph::kControlSlot, node1, Graph::kControlSlot); g.AddEdge(source, Graph::kControlSlot, node2, Graph::kControlSlot); - g.AddEdge(node3, Graph::kControlSlot, sink, Graph::kControlSlot); + g.AddEdge(node4, Graph::kControlSlot, sink, Graph::kControlSlot); const char* ng_backend_env_value = std::getenv("NGRAPH_TF_BACKEND"); string expected_backend{"CPU"}; @@ -75,9 +81,20 @@ TEST(MarkForClustering, SimpleTest) { ASSERT_OK(MarkForClustering(&g, {}, expected_backend)); string backend; + const set nodes_expected_to_be_marked{"node1", "node2", "node3", + "node4"}; for (auto node : g.op_nodes()) { ASSERT_OK(GetNodeBackend(node, &backend)); ASSERT_EQ(backend, expected_backend); + ASSERT_EQ(nodes_expected_to_be_marked.find(node->name()) != + nodes_expected_to_be_marked.end(), + NodeIsMarkedForClustering(node)); + } + + ResetMarkForClustering(&g); + for (auto node : g.op_nodes()) { + ASSERT_NOT_OK(GetNodeBackend(node, &backend)); + ASSERT_FALSE(NodeIsMarkedForClustering(node)); } } } diff --git a/test/graph_rewrites/op_by_op_capability_test.cc b/test/graph_rewrites/op_by_op_capability_test.cc index 1dd05756e..923104c9f 100644 --- a/test/graph_rewrites/op_by_op_capability_test.cc +++ b/test/graph_rewrites/op_by_op_capability_test.cc @@ -62,8 +62,7 @@ TEST(OpByOpCapability, Backend) { ASSERT_OK(BackendManager::GetCurrentlySetBackendName(&ng_backend_type)); // Map with all the backends, and what the boolean is_supported should be - std::map backend_map{ - {"CPU", true}, {"INTERPRETER", true}, {"NOP", false}}; + std::map backend_map{{"CPU", true}, {"INTERPRETER", true}}; // Tests three cases of (Backend, is_supported=true/false) // 1. CPU, true diff --git a/test/opexecuter.cpp b/test/opexecuter.cpp index 14156c8c5..2fb5a1fa6 100644 --- a/test/opexecuter.cpp +++ b/test/opexecuter.cpp @@ -342,6 +342,25 @@ void OpExecuter::ExecuteOnNGraph(vector& ngraph_outputs, ng_function)) << "Failed to TranslateGraph"; + std::set> TFtoNgraphOpSet = + GetTFToNgOpMap().at(test_op_type_); + + for (auto n : ng_function->get_ops()) { + auto ng_node = dynamic_pointer_cast(n); + bool is_result = (ng_node != nullptr); + if (!is_result && !(n->is_parameter())) { + bool found = false; + for (auto itr : TFtoNgraphOpSet) { + found = n->is_same_op_type(itr); + if (found) break; + } + ASSERT_TRUE(found) << "After translation found ngraph op " + << (n->get_name()) + << " which was not found in map. To fix this issue " + "check GetTFToNgOpMap"; + } + } + // ng function should get same number of outputs ASSERT_EQ(expected_output_datatypes_.size(), ng_function->get_output_size()) << "Number of outputs of requested outputs and ngraph function outputs " diff --git a/test/opexecuter.h b/test/opexecuter.h index b7542df7c..bffba9962 100644 --- a/test/opexecuter.h +++ b/test/opexecuter.h @@ -34,6 +34,7 @@ #include "logging/tf_graph_writer.h" #include "ngraph_bridge/ngraph_backend_manager.h" #include "ngraph_bridge/ngraph_builder.h" +#include "ngraph_bridge/ngraph_mark_for_clustering.h" #include "ngraph_bridge/ngraph_utils.h" #include "test/test_utilities.h" diff --git a/test/python/tensorflow/python_tests_list.txt b/test/python/tensorflow/python_tests_list.txt index 0c3cded52..f894ac8ba 100644 --- a/test/python/tensorflow/python_tests_list.txt +++ b/test/python/tensorflow/python_tests_list.txt @@ -398,6 +398,92 @@ relu_op_test.ReluTest.testGradientFloat32 relu_op_test.ReluTest.testGradientFloat64 relu_op_test.ReluTest.testGradientScalar +scan_ops_test.CumsumTest.test1D +scan_ops_test.CumsumTest.test2D +scan_ops_test.CumsumTest.test3D +scan_ops_test.CumsumTest.test6D +scan_ops_test.CumsumTest.testAxisType +scan_ops_test.CumsumTest.testEmpty +scan_ops_test.CumsumTest.testGradient +scan_ops_test.CumsumTest.testGradient2D +scan_ops_test.CumsumTest.testGradientExclusive +scan_ops_test.CumsumTest.testGradientExclusiveReverse +scan_ops_test.CumsumTest.testGradientReverse +#This test fails due to error string matching issue +#scan_ops_test.CumsumTest.testInvalidAxis +scan_ops_test.CumsumTest.testLarge +scan_ops_test.CumsumTest.test_session + +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testBool +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testEmptyOutputShape1 +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testEmptyOutputShape2 +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testEmptyOutputShape3 +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testExtraIndicesDimensions +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testGradientsRank2ElementUpdate +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testGradientsRank2SliceUpdate +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testGradientsRank3SliceUpdate +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testGradientsRank7SliceUpdate +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testInvalidShape +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testRank3InvalidShape1 +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testRank3InvalidShape2 +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testRank3ValidShape +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testScatterNdRepatedIndicesAdd +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testSmokeScatterNdBatch1DSliceDim2 +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testSmokeScatterNdBatch1DSliceDim3ShapeRank7 +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testSmokeScatterNdBatch2DSliceDim2 +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testSmokeScatterNdBatch2DSliceDim3ShapeRank7 +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testString +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testUndefinedIndicesShape +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testUndefinedOutputShape +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testUndefinedUpdatesShape +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.test_session +scatter_nd_ops_test.ScatterNdTensorTest.testTensorScatterUpdateWithForwarding +scatter_nd_ops_test.ScatterNdTensorTest.testUpdateAddSub +scatter_nd_ops_test.ScatterNdTensorTest.testUpdateAddSubGradients +scatter_nd_ops_test.ScatterNdTensorTest.test_session +# This test fails on CPU backend on char (and maybe other data types) +# scatter_nd_ops_test.ScatterNdTest.testBool +scatter_nd_ops_test.ScatterNdTest.testEmptyOutputShape1 +# TODO: Test failing due to incorrect error message +# scatter_nd_ops_test.ScatterNdTest.testEmptyOutputShape2 +scatter_nd_ops_test.ScatterNdTest.testEmptyOutputShape3 +# This test fails on CPU backend on some unsupported data types +# scatter_nd_ops_test.ScatterNdTest.testExtraIndicesDimensions +scatter_nd_ops_test.ScatterNdTest.testGradientsRank2ElementUpdate +scatter_nd_ops_test.ScatterNdTest.testGradientsRank2SliceUpdate +scatter_nd_ops_test.ScatterNdTest.testGradientsRank3SliceUpdate +scatter_nd_ops_test.ScatterNdTest.testGradientsRank7SliceUpdate +scatter_nd_ops_test.ScatterNdTest.testInvalidShape +scatter_nd_ops_test.ScatterNdTest.testRank3InvalidShape1 +scatter_nd_ops_test.ScatterNdTest.testRank3InvalidShape2 +scatter_nd_ops_test.ScatterNdTest.testRank3ValidShape +scatter_nd_ops_test.ScatterNdTest.testScatterNdRepatedIndicesAdd +scatter_nd_ops_test.ScatterNdTest.testSmokeScatterNdBatch1DSliceDim2 +scatter_nd_ops_test.ScatterNdTest.testSmokeScatterNdBatch1DSliceDim3ShapeRank7 +scatter_nd_ops_test.ScatterNdTest.testSmokeScatterNdBatch2DSliceDim2 +scatter_nd_ops_test.ScatterNdTest.testSmokeScatterNdBatch2DSliceDim3ShapeRank7 +scatter_nd_ops_test.ScatterNdTest.testString +scatter_nd_ops_test.ScatterNdTest.testUndefinedIndicesShape +scatter_nd_ops_test.ScatterNdTest.testUndefinedOutputShape +scatter_nd_ops_test.ScatterNdTest.testUndefinedUpdatesShape +scatter_nd_ops_test.ScatterNdTest.test_session +scatter_nd_ops_test.StatefulScatterNdTest.testConcurrentUpdates +scatter_nd_ops_test.StatefulScatterNdTest.testExtraIndicesDimensions +scatter_nd_ops_test.StatefulScatterNdTest.testRank3InvalidShape1 +scatter_nd_ops_test.StatefulScatterNdTest.testRank3InvalidShape2 +scatter_nd_ops_test.StatefulScatterNdTest.testRank3ValidShape +scatter_nd_ops_test.StatefulScatterNdTest.testResVarInvalidOutputShape +scatter_nd_ops_test.StatefulScatterNdTest.testScatterOutOfRangeCpu +#scatter_nd_ops_test.StatefulScatterNdTest.testScatterRepeatIndices +scatter_nd_ops_test.StatefulScatterNdTest.testSimple +scatter_nd_ops_test.StatefulScatterNdTest.testSimple2 +scatter_nd_ops_test.StatefulScatterNdTest.testSimple3 +scatter_nd_ops_test.StatefulScatterNdTest.testSimpleResource +#scatter_nd_ops_test.StatefulScatterNdTest.testVariableRankAdd +#scatter_nd_ops_test.StatefulScatterNdTest.testVariableRankSub +#scatter_nd_ops_test.StatefulScatterNdTest.testVariableRankUpdate +scatter_nd_ops_test.StatefulScatterNdTest.test_session + slice_op_test.SliceTest.testComplex slice_op_test.SliceTest.testEmpty slice_op_test.SliceTest.testGradientsAll diff --git a/test/python/tensorflow/python_tests_list_gpu.txt b/test/python/tensorflow/python_tests_list_gpu.txt index 4e779fa33..80729e7cb 100644 --- a/test/python/tensorflow/python_tests_list_gpu.txt +++ b/test/python/tensorflow/python_tests_list_gpu.txt @@ -390,6 +390,89 @@ relu_op_test.ReluTest.testGradientFloat32 relu_op_test.ReluTest.testGradientScalar relu_op_test.ReluTest.testNumbers +scan_ops_test.CumsumTest.test1D +scan_ops_test.CumsumTest.test2D +scan_ops_test.CumsumTest.test3D +scan_ops_test.CumsumTest.test6D +scan_ops_test.CumsumTest.testAxisType +scan_ops_test.CumsumTest.testEmpty +scan_ops_test.CumsumTest.testGradient +scan_ops_test.CumsumTest.testGradient2D +scan_ops_test.CumsumTest.testGradientExclusive +scan_ops_test.CumsumTest.testGradientExclusiveReverse +scan_ops_test.CumsumTest.testGradientReverse +#This test fails due to error string matching issue +#scan_ops_test.CumsumTest.testInvalidAxis +scan_ops_test.CumsumTest.testLarge +scan_ops_test.CumsumTest.test_session + +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testBool +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testEmptyOutputShape1 +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testEmptyOutputShape2 +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testEmptyOutputShape3 +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testExtraIndicesDimensions +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testGradientsRank2ElementUpdate +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testGradientsRank2SliceUpdate +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testGradientsRank3SliceUpdate +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testGradientsRank7SliceUpdate +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testInvalidShape +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testRank3InvalidShape1 +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testRank3InvalidShape2 +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testRank3ValidShape +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testScatterNdRepatedIndicesAdd +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testSmokeScatterNdBatch1DSliceDim2 +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testSmokeScatterNdBatch1DSliceDim3ShapeRank7 +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testSmokeScatterNdBatch2DSliceDim2 +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testSmokeScatterNdBatch2DSliceDim3ShapeRank7 +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testString +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testUndefinedIndicesShape +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testUndefinedOutputShape +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testUndefinedUpdatesShape +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.test_session +scatter_nd_ops_test.ScatterNdTensorTest.testTensorScatterUpdateWithForwarding +scatter_nd_ops_test.ScatterNdTensorTest.testUpdateAddSub +scatter_nd_ops_test.ScatterNdTensorTest.testUpdateAddSubGradients +scatter_nd_ops_test.ScatterNdTensorTest.test_session +scatter_nd_ops_test.ScatterNdTest.testBool +scatter_nd_ops_test.ScatterNdTest.testEmptyOutputShape1 +scatter_nd_ops_test.ScatterNdTest.testEmptyOutputShape2 +scatter_nd_ops_test.ScatterNdTest.testEmptyOutputShape3 +scatter_nd_ops_test.ScatterNdTest.testExtraIndicesDimensions +scatter_nd_ops_test.ScatterNdTest.testGradientsRank2ElementUpdate +scatter_nd_ops_test.ScatterNdTest.testGradientsRank2SliceUpdate +scatter_nd_ops_test.ScatterNdTest.testGradientsRank3SliceUpdate +scatter_nd_ops_test.ScatterNdTest.testGradientsRank7SliceUpdate +scatter_nd_ops_test.ScatterNdTest.testInvalidShape +scatter_nd_ops_test.ScatterNdTest.testRank3InvalidShape1 +scatter_nd_ops_test.ScatterNdTest.testRank3InvalidShape2 +scatter_nd_ops_test.ScatterNdTest.testRank3ValidShape +scatter_nd_ops_test.ScatterNdTest.testScatterNdRepatedIndicesAdd +scatter_nd_ops_test.ScatterNdTest.testSmokeScatterNdBatch1DSliceDim2 +scatter_nd_ops_test.ScatterNdTest.testSmokeScatterNdBatch1DSliceDim3ShapeRank7 +scatter_nd_ops_test.ScatterNdTest.testSmokeScatterNdBatch2DSliceDim2 +scatter_nd_ops_test.ScatterNdTest.testSmokeScatterNdBatch2DSliceDim3ShapeRank7 +scatter_nd_ops_test.ScatterNdTest.testString +scatter_nd_ops_test.ScatterNdTest.testUndefinedIndicesShape +scatter_nd_ops_test.ScatterNdTest.testUndefinedOutputShape +scatter_nd_ops_test.ScatterNdTest.testUndefinedUpdatesShape +scatter_nd_ops_test.ScatterNdTest.test_session +scatter_nd_ops_test.StatefulScatterNdTest.testConcurrentUpdates +scatter_nd_ops_test.StatefulScatterNdTest.testExtraIndicesDimensions +scatter_nd_ops_test.StatefulScatterNdTest.testRank3InvalidShape1 +scatter_nd_ops_test.StatefulScatterNdTest.testRank3InvalidShape2 +scatter_nd_ops_test.StatefulScatterNdTest.testRank3ValidShape +scatter_nd_ops_test.StatefulScatterNdTest.testResVarInvalidOutputShape +scatter_nd_ops_test.StatefulScatterNdTest.testScatterOutOfRangeCpu +#scatter_nd_ops_test.StatefulScatterNdTest.testScatterRepeatIndices +scatter_nd_ops_test.StatefulScatterNdTest.testSimple +scatter_nd_ops_test.StatefulScatterNdTest.testSimple2 +scatter_nd_ops_test.StatefulScatterNdTest.testSimple3 +scatter_nd_ops_test.StatefulScatterNdTest.testSimpleResource +#scatter_nd_ops_test.StatefulScatterNdTest.testVariableRankAdd +#scatter_nd_ops_test.StatefulScatterNdTest.testVariableRankSub +#scatter_nd_ops_test.StatefulScatterNdTest.testVariableRankUpdate +scatter_nd_ops_test.StatefulScatterNdTest.test_session + slice_op_test.SliceTest.testComplex slice_op_test.SliceTest.testEmpty slice_op_test.SliceTest.testGradientsAll diff --git a/test/python/tensorflow/python_tests_list_mac.txt b/test/python/tensorflow/python_tests_list_mac.txt index 4c4f078a0..863446129 100644 --- a/test/python/tensorflow/python_tests_list_mac.txt +++ b/test/python/tensorflow/python_tests_list_mac.txt @@ -398,6 +398,90 @@ relu_op_test.ReluTest.testGradientFloat32 relu_op_test.ReluTest.testGradientFloat64 relu_op_test.ReluTest.testGradientScalar +scan_ops_test.CumsumTest.test1D +scan_ops_test.CumsumTest.test2D +scan_ops_test.CumsumTest.test3D +scan_ops_test.CumsumTest.test6D +scan_ops_test.CumsumTest.testAxisType +scan_ops_test.CumsumTest.testEmpty +scan_ops_test.CumsumTest.testGradient +scan_ops_test.CumsumTest.testGradient2D +scan_ops_test.CumsumTest.testGradientExclusive +scan_ops_test.CumsumTest.testGradientExclusiveReverse +scan_ops_test.CumsumTest.testGradientReverse +#This test fails due to error string matching issue +#scan_ops_test.CumsumTest.testInvalidAxis +scan_ops_test.CumsumTest.testLarge +scan_ops_test.CumsumTest.test_session + +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testBool +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testEmptyOutputShape1 +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testEmptyOutputShape2 +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testEmptyOutputShape3 +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testExtraIndicesDimensions +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testGradientsRank2ElementUpdate +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testGradientsRank2SliceUpdate +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testGradientsRank3SliceUpdate +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testGradientsRank7SliceUpdate +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testInvalidShape +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testRank3InvalidShape1 +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testRank3InvalidShape2 +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testRank3ValidShape +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testScatterNdRepatedIndicesAdd +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testSmokeScatterNdBatch1DSliceDim2 +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testSmokeScatterNdBatch1DSliceDim3ShapeRank7 +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testSmokeScatterNdBatch2DSliceDim2 +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testSmokeScatterNdBatch2DSliceDim3ShapeRank7 +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testString +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testUndefinedIndicesShape +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testUndefinedOutputShape +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.testUndefinedUpdatesShape +scatter_nd_ops_test.ScatterNdNonAliasingAddTest.test_session +scatter_nd_ops_test.ScatterNdTensorTest.testTensorScatterUpdateWithForwarding +scatter_nd_ops_test.ScatterNdTensorTest.testUpdateAddSub +scatter_nd_ops_test.ScatterNdTensorTest.testUpdateAddSubGradients +scatter_nd_ops_test.ScatterNdTensorTest.test_session +# scatter_nd_ops_test.ScatterNdTest.testBool +scatter_nd_ops_test.ScatterNdTest.testEmptyOutputShape1 +# scatter_nd_ops_test.ScatterNdTest.testEmptyOutputShape2 +scatter_nd_ops_test.ScatterNdTest.testEmptyOutputShape3 +# scatter_nd_ops_test.ScatterNdTest.testExtraIndicesDimensions +scatter_nd_ops_test.ScatterNdTest.testGradientsRank2ElementUpdate +scatter_nd_ops_test.ScatterNdTest.testGradientsRank2SliceUpdate +scatter_nd_ops_test.ScatterNdTest.testGradientsRank3SliceUpdate +scatter_nd_ops_test.ScatterNdTest.testGradientsRank7SliceUpdate +scatter_nd_ops_test.ScatterNdTest.testInvalidShape +scatter_nd_ops_test.ScatterNdTest.testRank3InvalidShape1 +scatter_nd_ops_test.ScatterNdTest.testRank3InvalidShape2 +scatter_nd_ops_test.ScatterNdTest.testRank3ValidShape +scatter_nd_ops_test.ScatterNdTest.testScatterNdRepatedIndicesAdd +scatter_nd_ops_test.ScatterNdTest.testSmokeScatterNdBatch1DSliceDim2 +scatter_nd_ops_test.ScatterNdTest.testSmokeScatterNdBatch1DSliceDim3ShapeRank7 +scatter_nd_ops_test.ScatterNdTest.testSmokeScatterNdBatch2DSliceDim2 +scatter_nd_ops_test.ScatterNdTest.testSmokeScatterNdBatch2DSliceDim3ShapeRank7 +scatter_nd_ops_test.ScatterNdTest.testString +scatter_nd_ops_test.ScatterNdTest.testUndefinedIndicesShape +scatter_nd_ops_test.ScatterNdTest.testUndefinedOutputShape +scatter_nd_ops_test.ScatterNdTest.testUndefinedUpdatesShape +scatter_nd_ops_test.ScatterNdTest.test_session +scatter_nd_ops_test.StatefulScatterNdTest.testConcurrentUpdates +scatter_nd_ops_test.StatefulScatterNdTest.testExtraIndicesDimensions +scatter_nd_ops_test.StatefulScatterNdTest.testRank3InvalidShape1 +scatter_nd_ops_test.StatefulScatterNdTest.testRank3InvalidShape2 +scatter_nd_ops_test.StatefulScatterNdTest.testRank3ValidShape +scatter_nd_ops_test.StatefulScatterNdTest.testResVarInvalidOutputShape +scatter_nd_ops_test.StatefulScatterNdTest.testScatterOutOfRangeCpu +#scatter_nd_ops_test.StatefulScatterNdTest.testScatterRepeatIndices +scatter_nd_ops_test.StatefulScatterNdTest.testSimple +scatter_nd_ops_test.StatefulScatterNdTest.testSimple2 +scatter_nd_ops_test.StatefulScatterNdTest.testSimple3 +scatter_nd_ops_test.StatefulScatterNdTest.testSimpleResource +#scatter_nd_ops_test.StatefulScatterNdTest.testVariableRankAdd +#scatter_nd_ops_test.StatefulScatterNdTest.testVariableRankSub +#scatter_nd_ops_test.StatefulScatterNdTest.testVariableRankUpdate +scatter_nd_ops_test.StatefulScatterNdTest.test_session + + slice_op_test.SliceTest.testComplex slice_op_test.SliceTest.testEmpty slice_op_test.SliceTest.testGradientsAll diff --git a/test/python/test_const.py b/test/python/test_const.py new file mode 100644 index 000000000..19ed79476 --- /dev/null +++ b/test/python/test_const.py @@ -0,0 +1,95 @@ +# ============================================================================== +# Copyright 2018-2019 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""nGraph TensorFlow bridge Const operation test + +""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import pytest + +import tensorflow as tf +import os + +from common import NgraphTest + +# Uncomment for debugging; Also add -s in command like, e.g. +# (venv-tf-py3) [build_cmake]$ +# NGRAPH_TF_LOG_PLACEMENT=1 NGRAPH_TF_VLOG_LEVEL=6 pytest -s -k test_const_scalarval ../test/python/test_const.py +import logging +logging.basicConfig(level=logging.DEBUG) + + +class TestConstOperations(NgraphTest): + + def test_const_listvals(self): + zz = tf.constant([1, 2, 3, 4, 5, 6], dtype=float, shape=[2, 3]) + + def run_test(sess): + return sess.run(zz) + + assert ( + self.with_ngraph(run_test) == self.without_ngraph(run_test)).all() + + def test_const_listvals_2(self): + zz = tf.constant([[1, 2, 3], [4, 5, 6]], dtype=float, shape=[2, 3]) + + def run_test(sess): + return sess.run(zz) + + assert ( + self.with_ngraph(run_test) == self.without_ngraph(run_test)).all() + + def test_const_scalarval(self): + zz = tf.constant(-3, dtype=float, shape=[2, 3]) + + def run_test(sess): + return sess.run(zz) + + assert ( + self.with_ngraph(run_test) == self.without_ngraph(run_test)).all() + + def test_const_lastfill(self): + zz = tf.constant([1, 2], dtype=float, shape=[2, 3]) + + def run_test(sess): + return sess.run(zz) + + assert ( + self.with_ngraph(run_test) == self.without_ngraph(run_test)).all() + + def test_const_empty(self): + log = logging.getLogger('test_const_empty') + zz = tf.constant([], dtype=float, shape=[2, 3]) + + def run_test(sess): + log.debug('Invoking sess.run(zz)') + return sess.run(zz) + + # Ideally we want same behavior for both TF & NG, but for now we are deviating, + # NGraph will throw error, but TF will fill in zeros + # assert ( + # self.with_ngraph(run_test) == self.without_ngraph(run_test)).all() + + # Test to see that exception is raised in NG + try: + # This test is expected to fail currently + res = self.with_ngraph(run_test) + assert False, 'Failed, expected test to raise error' + except: + log.debug('Passed, expected NG to raise error...') + assert True diff --git a/test/python/test_maxpoolbackprop.py b/test/python/test_maxpoolbackprop.py index 5f2ffe535..e3cdadab2 100644 --- a/test/python/test_maxpoolbackprop.py +++ b/test/python/test_maxpoolbackprop.py @@ -33,31 +33,35 @@ np.random.seed(5) +B = 4 +C = 3 +A = 112 + class TestMaxPoolBackpropInput(NgraphTest): # NHWC - input_nhwc = np.random.rand(128, 224, 224, 3) + input_nhwc = np.random.rand(B, A, A, C) strides_nhwc = ksize_nhwc = [1, 2, 3, 1] output_nhwc = { - "VALID": np.random.rand(128, 112, 74, 3), - "SAME": np.random.rand(128, 112, 75, 3) + "VALID": np.random.rand(B, (A // 2), (A // 3), C), + "SAME": np.random.rand(B, (A // 2), (A // 3) + 1, C) } grad_nhwc = { - "VALID": np.random.rand(128, 112, 74, 3), - "SAME": np.random.rand(128, 112, 75, 3) + "VALID": np.random.rand(B, (A // 2), (A // 3), C), + "SAME": np.random.rand(B, (A // 2), (A // 3) + 1, C) } # NCHW input_nchw = np.transpose(input_nhwc, NHWC_TO_NCHW) - strides_nchw = ksize_nchw = [1, 1, 2, 3] + strides_nchw = ksize_nchw = [1, 1, 2, C] output_nchw = { - "VALID": np.random.rand(128, 3, 112, 74), - "SAME": np.random.rand(128, 3, 112, 75) + "VALID": np.random.rand(B, C, (A // 2), (A // 3)), + "SAME": np.random.rand(B, C, (A // 2), (A // 3) + 1) } grad_nchw = { - "VALID": np.random.rand(128, 3, 112, 74), - "SAME": np.random.rand(128, 3, 112, 75) + "VALID": np.random.rand(B, C, (A // 2), (A // 3)), + "SAME": np.random.rand(B, C, (A // 2), (A // 3) + 1) } @pytest.mark.parametrize("padding", ("VALID", "SAME")) @@ -67,9 +71,10 @@ def test_nhwc(self, padding): output = self.output_nhwc[padding] g_nhwc = self.grad_nhwc[padding] if padding == "VALID": - grad = tf.placeholder(tf.float32, shape=(128, 112, 74, 3)) + grad = tf.placeholder(tf.float32, shape=(B, (A // 2), (A // 3), C)) elif padding == "SAME": - grad = tf.placeholder(tf.float32, shape=(128, 112, 75, 3)) + grad = tf.placeholder( + tf.float32, shape=(B, (A // 2), (A // 3) + 1, C)) out = max_pool_grad( self.input_nhwc, output, @@ -89,9 +94,10 @@ def test_nchw(self, padding): output = self.output_nchw[padding] g_nchw = self.grad_nchw[padding] if padding == "VALID": - grad = tf.placeholder(tf.float32, shape=(128, 3, 112, 74)) + grad = tf.placeholder(tf.float32, shape=(B, C, (A // 2), (A // 3))) elif padding == "SAME": - grad = tf.placeholder(tf.float32, shape=(128, 3, 112, 75)) + grad = tf.placeholder( + tf.float32, shape=(B, C, (A // 2), (A // 3) + 1)) def test_on_ng(sess): a = max_pool_grad( diff --git a/test/python/test_sign.py b/test/python/test_sign.py index e24aabc63..c53ba26bf 100644 --- a/test/python/test_sign.py +++ b/test/python/test_sign.py @@ -35,7 +35,8 @@ def test_sign_1d(self, test_input, expected): val = tf.placeholder(tf.float32, shape=(1,)) out = tf.sign(val) sess_fn = lambda sess: sess.run((out,), feed_dict={val: (test_input,)}) - np.allclose(self.with_ngraph(sess_fn), self.without_ngraph(sess_fn)) + assert np.allclose( + self.with_ngraph(sess_fn), self.without_ngraph(sess_fn)) assert np.allclose(self.with_ngraph(sess_fn), expected) def test_sign_2d(self): diff --git a/test/test_array_ops.cpp b/test/test_array_ops.cpp index 4e4638a05..db61e5e40 100644 --- a/test/test_array_ops.cpp +++ b/test/test_array_ops.cpp @@ -843,7 +843,61 @@ TEST(ArrayOps, QuantizeAndDequantizeV2x8xtruexfalse) { output_datatypes, sess_run_fetchoutputs); opexecuter.RunTest(); -} // end of test op QuantizeAndDequantizeV2x8xtruexfalse +} + +TEST(ArrayOps, QuantizeAndDequantizeV2RoundingMode1) { + Scope root = Scope::NewRootScope(); + int dim1 = 2; + int dim2 = 3; + + Tensor A(DT_FLOAT, TensorShape({dim1, dim2})); + AssignInputValues(A, {0.9, 3.4, 2.6, 5.4, 4.2, 4.5}); + + auto attrs = ops::QuantizeAndDequantizeV2::Attrs(); + attrs.num_bits_ = 8; + attrs.range_given_ = true; + attrs.signed_input_ = true; + attrs.round_mode_ = "HALF_UP"; + + vector static_input_indexes = {1, 2}; + ops::QuantizeAndDequantizeV2 R = + ops::QuantizeAndDequantizeV2(root, A, 0.0f, 127.0f, attrs); + + vector output_datatypes = {DT_FLOAT}; + + std::vector sess_run_fetchoutputs = {R.output}; + OpExecuter opexecuter(root, "QuantizeAndDequantizeV2", static_input_indexes, + output_datatypes, sess_run_fetchoutputs); + + opexecuter.RunTest(); +} + +TEST(ArrayOps, QuantizeAndDequantizeV2RoundingMode2) { + Scope root = Scope::NewRootScope(); + int dim1 = 2; + int dim2 = 3; + + Tensor A(DT_FLOAT, TensorShape({dim1, dim2})); + AssignInputValues(A, {0.9, 3.4, 2.6, 5.4, 4.2, 4.5}); + + auto attrs = ops::QuantizeAndDequantizeV2::Attrs(); + attrs.num_bits_ = 8; + attrs.range_given_ = true; + attrs.signed_input_ = true; + attrs.round_mode_ = "HALF_TO_EVEN"; + + vector static_input_indexes = {1, 2}; + ops::QuantizeAndDequantizeV2 R = + ops::QuantizeAndDequantizeV2(root, A, 0.0f, 127.0f, attrs); + + vector output_datatypes = {DT_FLOAT}; + + std::vector sess_run_fetchoutputs = {R.output}; + OpExecuter opexecuter(root, "QuantizeAndDequantizeV2", static_input_indexes, + output_datatypes, sess_run_fetchoutputs); + + opexecuter.RunTest(); +} // end of test op QuantizeAndDequantizeV2x8xtruextrue // CPU only supports QuantizedConcat with DT_QINT32 and DT_QUINT8 TEST(ArrayOps, QuantizedConcat) { @@ -948,6 +1002,94 @@ TEST(ArrayOps, Rank) { opexecuter.RunTest(); } // end of RankOp +// Test op: ScatterNd Op +TEST(ArrayOps, ScatterNd1D) { + Tensor indices(DT_INT32, TensorShape({4, 1})); + Tensor updates(DT_FLOAT, TensorShape({4})); + + AssignInputValues(indices, {{2}, {3}, {1}, {7}}); + AssignInputValues(updates, {9.1, 10.2, -11.3, 12.4}); + + vector static_input_indexes = {2}; + + vector output_datatypes = {DT_FLOAT}; + + Scope root = Scope::NewRootScope(); + auto R = ops::ScatterNd(root, indices, updates, {8}); + std::vector sess_run_fetchoutputs = {R}; + + OpExecuter opexecuter(root, "ScatterNd", static_input_indexes, + output_datatypes, sess_run_fetchoutputs); + + opexecuter.RunTest(); +} + +TEST(ArrayOps, ScatterNdRepeatIndices) { + Tensor indices(DT_INT32, TensorShape({4, 1})); + Tensor updates(DT_FLOAT, TensorShape({4})); + + // the index "2" appears twice + AssignInputValues(indices, {{2}, {3}, {2}, {7}}); + AssignInputValues(updates, {9.1, 10.2, -11.3, 12.4}); + + vector static_input_indexes = {2}; + + vector output_datatypes = {DT_FLOAT}; + + Scope root = Scope::NewRootScope(); + auto R = ops::ScatterNd(root, indices, updates, {10}); + std::vector sess_run_fetchoutputs = {R}; + + OpExecuter opexecuter(root, "ScatterNd", static_input_indexes, + output_datatypes, sess_run_fetchoutputs); + + opexecuter.RunTest(); +} + +TEST(ArrayOps, ScatterNdComplex) { + // indices.shape[-1] <= shape.rank + // updates.shape = indices.shape[:-1] + shape[indices.shape[-1]:] + // shape must be rank 1 + Tensor indices(DT_INT32, TensorShape({2, 2, 2})); + Tensor updates(DT_FLOAT, TensorShape({2, 2, 2})); + + AssignInputValuesRandom(indices, 0, 1); + AssignInputValuesRandom(updates, -10.0, 20.0f); + + vector static_input_indexes = {2}; + + vector output_datatypes = {DT_FLOAT}; + + Scope root = Scope::NewRootScope(); + auto R = ops::ScatterNd(root, indices, updates, {2, 2, 2}); + std::vector sess_run_fetchoutputs = {R}; + + OpExecuter opexecuter(root, "ScatterNd", static_input_indexes, + output_datatypes, sess_run_fetchoutputs); + opexecuter.RunTest(); +} + +TEST(ArrayOps, ScatterNd3D) { + Tensor indices(DT_INT32, TensorShape({2, 1})); + Tensor updates(DT_FLOAT, TensorShape({2, 4, 4})); + + AssignInputValues(indices, {{0}, {2}}); + AssignInputValuesRandom(updates, -10.0, 20.0f); + + vector static_input_indexes = {2}; + + vector output_datatypes = {DT_FLOAT}; + + Scope root = Scope::NewRootScope(); + auto R = ops::ScatterNd(root, indices, updates, {4, 4, 4}); + std::vector sess_run_fetchoutputs = {R}; + + OpExecuter opexecuter(root, "ScatterNd", static_input_indexes, + output_datatypes, sess_run_fetchoutputs); + + opexecuter.RunTest(); +} // end of test op ScatterNd + // Test op: Shape, outputs the shape of a tensor TEST(ArrayOps, Shape2D) { Scope root = Scope::NewRootScope(); diff --git a/test/test_dummy_backend.cpp b/test/test_dummy_backend.cpp new file mode 100644 index 000000000..7423ada00 --- /dev/null +++ b/test/test_dummy_backend.cpp @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright 2017-2020 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +#include "gtest/gtest.h" + +#include "tensorflow/cc/client/client_session.h" +#include "tensorflow/cc/ops/standard_ops.h" +#include "tensorflow/core/framework/tensor.h" +#include "tensorflow/core/public/session.h" + +#include "logging/tf_graph_writer.h" +#include "test/dummy_backend.h" +#include "test/test_utilities.h" + +using namespace std; +namespace ng = ngraph; + +namespace tensorflow { + +namespace ngraph_bridge { + +namespace testing { + +// Test is_supported API +TEST(DummyBackend, IsSupported) { + ngraph::runtime::dummy::DummyBackend db; + auto add = std::make_shared(); + ASSERT_EQ(db.is_supported(*add), false); +} + +} // namespace testing +} // namespace ngraph_bridge +} // namespace tensorflow diff --git a/test/test_image_ops.cpp b/test/test_image_ops.cpp new file mode 100644 index 000000000..ab652abd2 --- /dev/null +++ b/test/test_image_ops.cpp @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright 2017-2019 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +#include "test/opexecuter.h" + +using namespace std; +namespace ng = ngraph; + +namespace tensorflow { + +namespace ngraph_bridge { + +namespace testing { + +// Test op: CropAndResize +// Disabled till a backend starts supporting it +// Add more tests when backend starts supporting + +TEST(ImageOps, DISABLED_CropAndResize) { + Scope root = Scope::NewRootScope(); + + // TODO check if assigning random values is ok, + // or we should probably assign some known in-range values + // Fix and enable this test when a backend supports CropAndResize + + // [batch, height, width, channels] + Tensor image(DT_FLOAT, TensorShape({4, 64, 64, 3})); + AssignInputValuesRandom(image); + + int num_boxes = 5; + // [num_boxes, 4] + Tensor boxes(DT_FLOAT, TensorShape({num_boxes, 4})); + AssignInputValuesRandom(boxes); + + // [num_boxes] + Tensor box_ind(DT_INT32, TensorShape({num_boxes})); + AssignInputValuesRandom(box_ind); + + // [crop_height, crop_width] + Tensor crop_size(DT_INT32, TensorShape({6, 5})); + AssignInputValuesRandom(crop_size); + + // TODO check with non-zero extrapolation value and method="nearest" + auto attr = + ops::CropAndResize::Attrs().ExtrapolationValue(0.0).Method("bilinear"); + + vector static_input_indexes = {}; + auto R = ops::CropAndResize(root, image, boxes, box_ind, crop_size, attr); + vector output_datatypes = {DT_FLOAT}; + + std::vector sess_run_fetchoutputs = {R}; + OpExecuter opexecuter(root, "CropAndResize", static_input_indexes, + output_datatypes, sess_run_fetchoutputs); + + opexecuter.RunTest(); +} + +// Test op: ResizeBilinear +// Disabled till a backend starts supporting it +TEST(ImageOps, DISABLED_ResizeBilinear) { + for (auto align : {true, false}) { + Scope root = Scope::NewRootScope(); + // [batch, height, width, channels] + Tensor images(DT_FLOAT, TensorShape({4, 64, 64, 3})); + AssignInputValuesRandom(images); + + // Todo: test by changing align_corners + + // new_height, new_width + Tensor size(DT_INT32, TensorShape({2})); + vector new_dims = {93, 27}; + // TODO loop and do multiple sizes, larger + // and smaller than original + AssignInputValues(size, new_dims); + + auto attr = ops::ResizeBilinear::Attrs().AlignCorners(align); + + vector static_input_indexes = {}; + auto R = ops::ResizeBilinear(root, images, size, attr); + vector output_datatypes = {DT_FLOAT}; + + std::vector sess_run_fetchoutputs = {R}; + OpExecuter opexecuter(root, "ResizeBilinear", static_input_indexes, + output_datatypes, sess_run_fetchoutputs); + + opexecuter.RunTest(); + } +} +} +} +} diff --git a/test/test_math_ops.cpp b/test/test_math_ops.cpp index 5e1c686f1..0366ba658 100644 --- a/test/test_math_ops.cpp +++ b/test/test_math_ops.cpp @@ -335,6 +335,31 @@ TEST(MathOps, AllPositiveAxis) { opexecuter.RunTest(); } // end of test op All +// Test op: Cumsum +TEST(MathOps, Cumsum) { + Scope root = Scope::NewRootScope(); + int dim1 = 2; + int dim2 = 2; + + Tensor A(DT_FLOAT, TensorShape({dim1, dim2})); + Tensor B(DT_INT32, TensorShape({})); + + AssignInputValues(A, 2.1f); + AssignInputValues(B, 0); + + vector static_input_indexes = {}; + auto attrs = ops::Cumsum::Attrs(); + attrs.exclusive_ = true; + attrs.reverse_ = true; + auto R = ops::Cumsum(root, A, B, attrs); + + vector output_datatypes = {DT_FLOAT}; + std::vector sess_run_fetchoutputs = {R}; + OpExecuter opexecuter(root, "Cumsum", static_input_indexes, output_datatypes, + sess_run_fetchoutputs); + opexecuter.RunTest(); +} // end of test op Cumsum + // Test op: Sum with & without keep dims & with both positive & negative axis TEST(MathOps, Sum) { int dim1 = 2; @@ -526,6 +551,29 @@ TEST(MathOps, ArgMinPos) { opexecuter.RunTest(); } // end of test op ArgMin +// Test op: Atan2 +TEST(MathOps, Atan2) { + Scope root = Scope::NewRootScope(); + int dim1 = 2; + int dim2 = 5; + + Tensor A(DT_FLOAT, TensorShape({dim1, dim2})); + Tensor B(DT_FLOAT, TensorShape({dim1, dim2})); + + AssignInputValues(A, {0, -0, 3, -3.5, 1.2, 3, 5, -4.5, 1.0, -7.0}); + AssignInputValues(B, {0, -0, 3, 2.5, -0.7, 2, 3.4, -5.6, 30, 0.06}); + + vector static_input_indexes = {}; + auto R = ops::Atan2(root, A, B); + + vector output_datatypes = {DT_FLOAT}; + std::vector sess_run_fetchoutputs = {R}; + OpExecuter opexecuter(root, "Atan2", static_input_indexes, output_datatypes, + sess_run_fetchoutputs); + + opexecuter.RunTest(); +} // end of test op Atan2 + // Test op: BatchMatMul // BatchMatMul2D // AdjX = false @@ -1724,6 +1772,30 @@ TEST(MathOps, MinimumBroadcasting) { opexecuter.RunTest(); } // end of test op MinimumBroadcasting +// Test op: MaximumBroadcasting +TEST(MathOps, MaximumBroadcasting) { + Scope root = Scope::NewRootScope(); + int dim1 = 2; + int dim2 = 2; + + Tensor A(DT_FLOAT, TensorShape({dim1, dim2})); + Tensor B(DT_FLOAT, TensorShape({dim1})); + + AssignInputValues(A, 7.5f); + AssignInputValues(B, 5.2f); + + vector static_input_indexes = {}; + auto R = ops::Maximum(root, A, B); + + vector output_datatypes = {DT_FLOAT}; + + std::vector sess_run_fetchoutputs = {R}; + OpExecuter opexecuter(root, "Maximum", static_input_indexes, output_datatypes, + sess_run_fetchoutputs); + + opexecuter.RunTest(); +} // end of test op MaximumBroadcasting + // Test op: Negate TEST(MathOps, Negate) { Scope root = Scope::NewRootScope(); diff --git a/test/test_ngraph_exec.cpp b/test/test_ngraph_exec.cpp index f34f8a53e..3bbec92b1 100644 --- a/test/test_ngraph_exec.cpp +++ b/test/test_ngraph_exec.cpp @@ -44,6 +44,13 @@ class NGraphExecTest : public ::testing::Test { GraphDef gdef; TF_RETURN_IF_ERROR(ReadTextProto(Env::Default(), graph_pbtxt_file, &gdef)); GraphConstructorOptions opts; + +// Register backends for static linking +#if defined(NGRAPH_BRIDGE_STATIC_LIB_ENABLE) + ngraph_register_cpu_backend(); + ngraph_register_interpreter_backend(); +#endif + // Set the allow_internal_ops to true so that graphs with node names such as // _arg_Placeholder_1_0_1_0_arg are allowed. These op names are generated // during the graph rewrite passes and considered internal diff --git a/tools/Dockerfile.ubuntu18.04 b/tools/Dockerfile.ubuntu18.04 index aacbfd52b..4782df656 100644 --- a/tools/Dockerfile.ubuntu18.04 +++ b/tools/Dockerfile.ubuntu18.04 @@ -18,10 +18,6 @@ FROM ubuntu:18.04 -# Setup the environment -ENV https_proxy http://proxy-chain.intel.com:912 -ENV http_proxy http://proxy-chain.intel.com:911 - RUN apt-get update && apt-get install -y \ vim \ python \