From ea6422491ec75504e78a63db029e7f74ec3479a5 Mon Sep 17 00:00:00 2001 From: Abhishek Kulkarni Date: Thu, 4 Feb 2021 16:56:44 -0800 Subject: [PATCH] Refactoring to separate TF and nGraph APIs (#798) * Remove TF Status/Errors from bridge internal API. Use exceptions instead. * Split TF and bridge utils into separate files * Use absl string split and join functions instead of ngraph join and split * Move TF op supported check inside backend * Add Backend::name() to get a backend's name * Remove nGraph tracing --- examples/cpp/infer_multiple_networks.cc | 68 ++--- examples/cpp/infer_single_network.cc | 26 +- ngraph_bridge/CMakeLists.txt | 1 + ngraph_bridge/api.cc | 14 +- ngraph_bridge/api.h | 1 + ngraph_bridge/assign_clusters.cc | 8 +- ngraph_bridge/backend.cc | 196 ++++++++++++++- ngraph_bridge/backend.h | 4 +- ngraph_bridge/backend_manager.cc | 52 ++-- ngraph_bridge/backend_manager.h | 11 +- ngraph_bridge/deassign_clusters.cc | 4 +- ngraph_bridge/encapsulate_clusters.cc | 4 +- ngraph_bridge/executable.cc | 4 +- .../kernels/ngraph_encapsulate_op.cc | 106 ++++---- ngraph_bridge/log.h | 1 - ngraph_bridge/mark_for_clustering.cc | 234 +----------------- ngraph_bridge/mark_for_clustering.h | 3 - ngraph_bridge/ngraph_builder.cc | 24 +- ngraph_bridge/ngraph_rewrite_pass.cc | 16 +- ngraph_bridge/pass/transpose_sinking.cc | 8 +- ngraph_bridge/tf_utils.cc | 224 +++++++++++++++++ ngraph_bridge/tf_utils.h | 62 +++++ ngraph_bridge/utils.cc | 203 +-------------- ngraph_bridge/utils.h | 40 +-- test/graph_rewrites/backend_manager_test.cc | 38 ++- .../op_by_op_capability_test.cc | 12 +- test/test_thread_safe_queue.cc | 45 ++-- test/tf_exec.cpp | 1 + 28 files changed, 668 insertions(+), 742 deletions(-) create mode 100644 ngraph_bridge/tf_utils.cc create mode 100644 ngraph_bridge/tf_utils.h diff --git a/examples/cpp/infer_multiple_networks.cc b/examples/cpp/infer_multiple_networks.cc index 292987151..5347892b1 100644 --- a/examples/cpp/infer_multiple_networks.cc +++ b/examples/cpp/infer_multiple_networks.cc @@ -35,7 +35,6 @@ #include "ngraph_bridge/backend_manager.h" #include "ngraph_bridge/timer.h" -#include "ngraph_bridge/utils.h" #include "ngraph_bridge/version.h" #include "inference_engine.h" @@ -62,15 +61,6 @@ void PrintAvailableBackends() { } } -// Sets the specified backend. This backend must be set BEFORE running -// the computation -tf::Status SetNGraphBackend(const string& backend_name) { - // Select a backend - tf::Status status = - tf::ngraph_bridge::BackendManager::SetBackend(backend_name); - return status; -} - void PrintVersion() { // Tensorflow version info std::cout << "Tensorflow version: " << tensorflow::ngraph_bridge::tf_version() @@ -158,12 +148,6 @@ int main(int argc, char** argv) { return -1; } - const char* backend = "CPU"; - if (SetNGraphBackend(backend) != tf::Status::OK()) { - std::cout << "Error: Cannot set the backend: " << backend << std::endl; - return -1; - } - std::cout << "Component versions\n"; PrintVersion(); @@ -194,27 +178,23 @@ int main(int argc, char** argv) { TF_CHECK_OK(benchmark::InferenceEngine::CreateSession(graph, session_three)); session_db[session_three.get()] = "Three"; std::vector outputs; - { - NG_TRACE("Compilation", "Compilation", ""); - - // - // Warm-up i.e., Call it onces to get the nGraph compilation done - // - Tensor next_image; - TF_CHECK_OK(inference_engine.GetNextImage(next_image)); - // Run inference once. This will trigger a compilation - tf::ngraph_bridge::Timer compilation_time; - TF_CHECK_OK(session_one->Run({{input_layer, next_image}}, {output_layer}, - {}, &outputs)); - TF_CHECK_OK(session_two->Run({{input_layer, next_image}}, {output_layer}, + // + // Warm-up i.e., Call it onces to get the nGraph compilation done + // + Tensor next_image; + TF_CHECK_OK(inference_engine.GetNextImage(next_image)); + // Run inference once. This will trigger a compilation + tf::ngraph_bridge::Timer compilation_time; + TF_CHECK_OK(session_one->Run({{input_layer, next_image}}, {output_layer}, {}, + &outputs)); + TF_CHECK_OK(session_two->Run({{input_layer, next_image}}, {output_layer}, {}, + &outputs)); + TF_CHECK_OK(session_three->Run({{input_layer, next_image}}, {output_layer}, {}, &outputs)); - TF_CHECK_OK(session_three->Run({{input_layer, next_image}}, {output_layer}, - {}, &outputs)); - compilation_time.Stop(); + compilation_time.Stop(); - cout << "Compilation took: " << compilation_time.ElapsedInMS() << " ms" - << endl; - } + cout << "Compilation took: " << compilation_time.ElapsedInMS() << " ms" + << endl; // // Add these sessions to the queue // @@ -241,8 +221,6 @@ int main(int argc, char** argv) { // Run the inference loop //----------------------------------------- for (int i = 0; i < iteration_count; i++) { - NG_TRACE(oss.str(), to_string(i), ""); - tf::ngraph_bridge::Timer get_image_timer; // // Get the image @@ -255,21 +233,15 @@ int main(int argc, char** argv) { // Get the next available network model (i.e., session) // tf::ngraph_bridge::Timer execute_inference_timer; - unique_ptr next_available_session; - { - NG_TRACE("Get Session", string("Iteration") + to_string(i), ""); - next_available_session = session_queue.GetNextAvailable(); - } + unique_ptr next_available_session = + session_queue.GetNextAvailable(); // // Run inference on this network model (i.e., session) // - { - NG_TRACE("Run Session", string("Iteration") + to_string(i), ""); - TF_CHECK_OK(next_available_session->Run({{input_layer, next_image}}, - {output_layer}, {}, - &output_each_thread)); - } + TF_CHECK_OK(next_available_session->Run({{input_layer, next_image}}, + {output_layer}, {}, + &output_each_thread)); Session* next_session_ptr = next_available_session.get(); session_queue.Add(move(next_available_session)); execute_inference_timer.Stop(); diff --git a/examples/cpp/infer_single_network.cc b/examples/cpp/infer_single_network.cc index bfe59f4fa..3f5f1ee42 100644 --- a/examples/cpp/infer_single_network.cc +++ b/examples/cpp/infer_single_network.cc @@ -35,7 +35,6 @@ #include "inference_engine.h" #include "ngraph_bridge/backend_manager.h" #include "ngraph_bridge/timer.h" -#include "ngraph_bridge/utils.h" #include "ngraph_bridge/version.h" using namespace std; @@ -163,20 +162,16 @@ int main(int argc, char** argv) { Tensor next_image; std::vector outputs; - { - NG_TRACE("Compilation", "Compilation", ""); - - // Call it onces to get the nGraph compilation done - TF_CHECK_OK(inference_engine.GetNextImage(next_image)); - // Run inference once. This will trigger a compilation - tf::ngraph_bridge::Timer compilation_time; - TF_CHECK_OK(the_session->Run({{input_layer, next_image}}, {output_layer}, - {}, &outputs)); - compilation_time.Stop(); - - cout << "Compilation took: " << compilation_time.ElapsedInMS() << " ms" - << endl; - } + // Call it onces to get the nGraph compilation done + TF_CHECK_OK(inference_engine.GetNextImage(next_image)); + // Run inference once. This will trigger a compilation + tf::ngraph_bridge::Timer compilation_time; + TF_CHECK_OK(the_session->Run({{input_layer, next_image}}, {output_layer}, {}, + &outputs)); + compilation_time.Stop(); + + cout << "Compilation took: " << compilation_time.ElapsedInMS() << " ms" + << endl; atomic total_time_in_ms{0}; atomic total_images_processed{0}; @@ -185,7 +180,6 @@ int main(int argc, char** argv) { ostringstream oss; oss << "Worker_" << worker_id; for (int i = 0; i < iteration_count; i++) { - NG_TRACE(oss.str(), to_string(i), ""); tf::ngraph_bridge::Timer iteration_timer; // Get the image Tensor next_image; diff --git a/ngraph_bridge/CMakeLists.txt b/ngraph_bridge/CMakeLists.txt index 430006840..12c843263 100644 --- a/ngraph_bridge/CMakeLists.txt +++ b/ngraph_bridge/CMakeLists.txt @@ -47,6 +47,7 @@ set(SRC pass/transpose_sinking.cc tf_graphcycles.cc tf_deadness_analysis.cc + tf_utils.cc utils.cc version.cc ) diff --git a/ngraph_bridge/api.cc b/ngraph_bridge/api.cc index 7bf3b3040..5dbf6bcec 100644 --- a/ngraph_bridge/api.cc +++ b/ngraph_bridge/api.cc @@ -76,15 +76,21 @@ bool IsEnabled() { return _is_enabled; } vector ListBackends() { return BackendManager::GetSupportedBackends(); } bool SetBackend(const string& type) { - return (BackendManager::SetBackend(type) == Status::OK()); + try { + BackendManager::SetBackend(type); + } catch (...) { + return false; + } + return true; } string GetBackend() { - string backend; - if (BackendManager::GetBackendName(backend) != Status::OK()) { + try { + auto backend = BackendManager::GetBackend(); + return backend->Name(); + } catch (...) { return ""; } - return backend; } void StartLoggingPlacement() { _is_logging_placement = true; } diff --git a/ngraph_bridge/api.h b/ngraph_bridge/api.h index 713522261..b469766dd 100644 --- a/ngraph_bridge/api.h +++ b/ngraph_bridge/api.h @@ -59,6 +59,7 @@ extern void StopLoggingPlacement(); extern bool IsLoggingPlacement(); extern std::set GetDisabledOps(); + extern void SetDisabledOps(std::set); extern void SetDisabledOps(string); diff --git a/ngraph_bridge/assign_clusters.cc b/ngraph_bridge/assign_clusters.cc index ecd3a3f50..0f785f8f3 100644 --- a/ngraph_bridge/assign_clusters.cc +++ b/ngraph_bridge/assign_clusters.cc @@ -18,6 +18,8 @@ #include #include +#include "absl/strings/str_join.h" +#include "absl/strings/str_split.h" #include "tensorflow/core/framework/attr_value_util.h" #include "tensorflow/core/framework/graph.pb.h" #include "tensorflow/core/framework/node_def_util.h" @@ -33,7 +35,6 @@ #include "mark_for_clustering.h" #include "tf_deadness_analysis.h" #include "tf_graphcycles.h" -#include "utils.h" using namespace std; @@ -650,7 +651,8 @@ Status AssignClusters(Graph* graph) { "assigned an encapsulate)\n"; for (auto it : cluster_separation_reason) { num_non_contracted += it.second.size(); - auto cluster_id_vector = ngraph::split(it.first, ','); + std::vector cluster_id_vector = + absl::StrSplit(it.first, ','); // function to find if this cluster became an ngraph_cluster // returns ngraph_cluster id if yes, else returns -1 auto find_in_map = [&cluster_to_encapsulate, &cluster_id_vector](int x) { @@ -688,7 +690,7 @@ Status AssignClusters(Graph* graph) { to_string(dst_encapsulate) + "] predicate: " + std::get<1>(deadness_predicates_tpl) + " Neighbours predicates: " + - ngraph::join(std::get<2>(deadness_predicates_tpl)) + "\n"); + absl::StrJoin(std::get<2>(deadness_predicates_tpl), "\n")); } } reason_count_clusters[inner_itr]++; diff --git a/ngraph_bridge/backend.cc b/ngraph_bridge/backend.cc index 80d0b6c67..098af6241 100644 --- a/ngraph_bridge/backend.cc +++ b/ngraph_bridge/backend.cc @@ -14,11 +14,13 @@ // limitations under the License. //***************************************************************************** -#include "backend.h" - #include #include "ngraph/ngraph.hpp" +#include "backend.h" +#include "default_opset.h" +#include "log.h" + using namespace std; using namespace ngraph; @@ -43,13 +45,191 @@ shared_ptr Backend::Compile(shared_ptr func, return make_shared(func, m_device); } -bool Backend::IsSupported(const Node& node) const { - // TODO: check if the given backend/device supports the op. Right now we're - // assuming - // that the selected backend supports all opset5 ops +static std::map>> + TFtoNgraphOpMap{ + {"Abs", {std::make_shared()}}, + {"Acos", {std::make_shared()}}, + {"Acosh", {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(), std::make_shared()}}, + {"ArgMin", + {std::make_shared(), std::make_shared()}}, + {"Asin", {std::make_shared()}}, + {"Asinh", {std::make_shared()}}, + {"Atan", {std::make_shared()}}, + {"Atanh", {std::make_shared()}}, + {"AvgPool", {std::make_shared()}}, + {"BiasAdd", + {std::make_shared(), std::make_shared()}}, + {"Cast", {std::make_shared()}}, + {"Ceil", {std::make_shared()}}, + {"ConcatV2", {std::make_shared()}}, + {"Const", {}}, + {"Conv2D", + {std::make_shared(), + std::make_shared()}}, + {"Conv2DBackpropInput", + {std::make_shared(), + std::make_shared()}}, + {"Conv3D", + {std::make_shared(), + std::make_shared()}}, + {"Cos", {std::make_shared()}}, + {"Cosh", {std::make_shared()}}, + {"Cumsum", {std::make_shared()}}, + {"DepthToSpace", {std::make_shared()}}, + {"DepthwiseConv2dNative", + {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()}}, + {"FusedBatchNorm", {std::make_shared()}}, + {"FusedBatchNormV2", + {std::make_shared(), + std::make_shared()}}, + {"FusedBatchNormV3", + {std::make_shared(), + std::make_shared()}}, + {"Gather", {std::make_shared()}}, + {"GatherV2", {std::make_shared()}}, + {"_FusedConv2D", + {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()}}, + {"Greater", {std::make_shared()}}, + {"GreaterEqual", {std::make_shared()}}, + {"Identity", {}}, + {"IsFinite", + {std::make_shared(), std::make_shared(), + std::make_shared()}}, + {"L2Loss", + {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()}}, + {"Less", {std::make_shared()}}, + {"LessEqual", {std::make_shared()}}, + {"Log", {std::make_shared()}}, + {"Log1p", + {std::make_shared(), std::make_shared()}}, + {"LogicalAnd", {std::make_shared()}}, + {"LogicalNot", {std::make_shared()}}, + {"LogicalOr", {std::make_shared()}}, + {"LRN", {std::make_shared()}}, + {"MatMul", {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()}}, + {"Mean", {std::make_shared()}}, + {"Min", {std::make_shared()}}, + {"Minimum", {std::make_shared()}}, + {"MirrorPad", {std::make_shared()}}, + {"Mul", {std::make_shared()}}, + {"Mod", {std::make_shared()}}, + {"Neg", {std::make_shared()}}, + {"NotEqual", {std::make_shared()}}, + {"NonMaxSuppressionV2", + {std::make_shared(), + std::make_shared(), + std::make_shared()}}, + {"OneHot", {std::make_shared()}}, + {"Pack", + {std::make_shared(), + std::make_shared()}}, + {"Pad", {std::make_shared()}}, + {"PadV2", {std::make_shared()}}, + {"Pow", {std::make_shared()}}, + {"Prod", {std::make_shared()}}, + {"Range", {std::make_shared()}}, + {"Rank", {}}, + {"RealDiv", {std::make_shared()}}, + {"Reciprocal", {std::make_shared()}}, + {"Relu", {std::make_shared()}}, + {"Relu6", {std::make_shared()}}, + {"Rsqrt", {std::make_shared()}}, + {"Select", {std::make_shared()}}, + {"SelectV2", {std::make_shared()}}, + {"Reshape", {std::make_shared()}}, + {"Shape", {std::make_shared()}}, + {"Sigmoid", {std::make_shared()}}, + {"Sin", {std::make_shared()}}, + {"Sinh", {std::make_shared()}}, + {"Size", {}}, + {"Sign", {std::make_shared()}}, + {"Slice", {std::make_shared()}}, + {"Snapshot", {}}, + {"Softmax", {std::make_shared()}}, + {"Softplus", {std::make_shared()}}, + {"SpaceToDepth", {std::make_shared()}}, + {"Split", {std::make_shared()}}, + {"SplitV", {std::make_shared()}}, + {"Sqrt", {std::make_shared()}}, + {"Square", {std::make_shared()}}, + {"SquaredDifference", {std::make_shared()}}, + {"Squeeze", {std::make_shared()}}, + {"StridedSlice", {std::make_shared()}}, + {"Sub", {std::make_shared()}}, + {"Sum", {std::make_shared()}}, + {"Tan", {std::make_shared()}}, + {"Tanh", {std::make_shared()}}, + {"Tile", {std::make_shared()}}, + {"TopKV2", {std::make_shared()}}, + {"Transpose", {std::make_shared()}}, + {"Where", + {std::make_shared(), + std::make_shared()}}, + {"Xdivy", + {std::make_shared(), std::make_shared(), + std::make_shared()}}, + {"Unpack", {std::make_shared()}}, + {"ZerosLike", {}}, + {"NoOp", {}}, + }; + +bool Backend::IsSupported(const char* op) const { + string op_(op); + auto ng_op = TFtoNgraphOpMap.find(op_); + if (ng_op == TFtoNgraphOpMap.end()) { + NGRAPH_VLOG(0) << "TF Op is not found in the map: " << op; + return false; + } + + // Loop through the ngraph op list to query const auto& opset = ngraph::get_opset5(); - return opset.contains_op_type(&node); + for (auto it = ng_op->second.begin(); it != ng_op->second.end(); it++) { + // TODO: check if the given backend/device supports the op. Right now we're + // assuming + // that the selected backend supports all opset5 ops + ngraph::Node& node = **it; + if (!opset.contains_op_type(&node)) { + return false; + } + } + return true; } } // namespace ngraph_bridge -} // namespace tensorflow \ No newline at end of file +} // namespace tensorflow diff --git a/ngraph_bridge/backend.h b/ngraph_bridge/backend.h index ef3c63a56..8ec5da8bc 100644 --- a/ngraph_bridge/backend.h +++ b/ngraph_bridge/backend.h @@ -35,7 +35,9 @@ class Backend { shared_ptr Compile(shared_ptr func, bool enable_performance_data = false); - bool IsSupported(const ngraph::Node& node) const; + + bool IsSupported(const char*) const; + string& Name() { return m_device; } private: string m_device; diff --git a/ngraph_bridge/backend_manager.cc b/ngraph_bridge/backend_manager.cc index 9709b7126..43ce3a792 100644 --- a/ngraph_bridge/backend_manager.cc +++ b/ngraph_bridge/backend_manager.cc @@ -14,8 +14,6 @@ * limitations under the License. *******************************************************************************/ -#include "tensorflow/core/lib/core/errors.h" - #include #include "backend_manager.h" @@ -27,59 +25,42 @@ namespace tensorflow { namespace ngraph_bridge { shared_ptr BackendManager::m_backend; -string BackendManager::m_backend_name; mutex BackendManager::m_backend_mutex; BackendManager::~BackendManager() { NGRAPH_VLOG(2) << "BackendManager::~BackendManager()"; } -Status BackendManager::SetBackend(const string& backend_name) { +void BackendManager::SetBackend(const string& backend_name) { NGRAPH_VLOG(2) << "BackendManager::SetBackend(" << backend_name << ")"; shared_ptr backend; string bname(backend_name); - auto status = CreateBackend(backend, bname); - if (!status.ok() || backend == nullptr) { - return errors::Internal("Failed to set backend: ", status.error_message()); + try { + CreateBackend(backend, bname); + } catch (const std::exception& e) { + throw runtime_error("Failed to set backend: " + string(e.what())); } lock_guard lock(m_backend_mutex); m_backend = backend; - m_backend_name = bname; - return Status::OK(); } shared_ptr BackendManager::GetBackend() { NGRAPH_VLOG(2) << "BackendManager::GetBackend()"; if (m_backend == nullptr) { - auto status = SetBackend(); - if (!status.ok()) { - NGRAPH_VLOG(0) << "Failed to get backend: " << status.error_message(); - throw errors::Internal("Failed to get backend: ", status.error_message()); + try { + SetBackend(); + } catch (const std::exception& e) { + NGRAPH_VLOG(0) << "Failed to get backend: " << e.what(); + throw runtime_error("Failed to get backend: " + string(e.what())); } } lock_guard lock(m_backend_mutex); return m_backend; } -Status BackendManager::GetBackendName(string& backend_name) { - NGRAPH_VLOG(2) << "BackendManager::GetBackendName()"; - if (m_backend == nullptr) { - auto status = SetBackend(); - if (!status.ok()) { - NGRAPH_VLOG(0) << "Failed to get backend name: " - << status.error_message(); - return errors::Internal("Failed to get backend name: ", - status.error_message()); - } - } - lock_guard lock(m_backend_mutex); - backend_name = m_backend_name; - return Status::OK(); -} - -Status BackendManager::CreateBackend(shared_ptr& backend, - string& backend_name) { +void BackendManager::CreateBackend(shared_ptr& backend, + string& backend_name) { const char* env = std::getenv("NGRAPH_TF_BACKEND"); if (env != nullptr && strlen(env) > 0) { backend_name = string(env); @@ -88,16 +69,15 @@ Status BackendManager::CreateBackend(shared_ptr& backend, try { backend = make_shared(backend_name); } catch (const std::exception& e) { - return errors::Internal("Could not create backend of type ", backend_name, - ". Got exception: ", e.what()); + throw runtime_error("Could not create backend of type " + backend_name + + ". Got exception: " + e.what()); } if (backend == nullptr) { - return errors::Internal("Could not create backend of type ", backend_name, - " got nullptr"); + throw runtime_error("Could not create backend of type " + backend_name + + " got nullptr"); } NGRAPH_VLOG(2) << "BackendManager::CreateBackend(): " << backend_name; - return Status::OK(); } // Returns the supported backend names diff --git a/ngraph_bridge/backend_manager.h b/ngraph_bridge/backend_manager.h index 6db400cd1..89d67e4f2 100644 --- a/ngraph_bridge/backend_manager.h +++ b/ngraph_bridge/backend_manager.h @@ -23,8 +23,6 @@ #include #include -#include "tensorflow/core/lib/core/status.h" - #include "backend.h" using namespace std; @@ -38,23 +36,18 @@ class BackendManager { static vector GetSupportedBackends(); // Set the BackendManager backend ng_backend_name_ - static Status SetBackend(const string& backend_name = "CPU"); + static void SetBackend(const string& backend_name = "CPU"); // Returns the currently set backend static shared_ptr GetBackend(); - // Returns the currently set backend's name - static Status GetBackendName(string& backend_name); - ~BackendManager(); private: // Creates backend of backend_name type - static Status CreateBackend(shared_ptr& backend, - string& backend_name); + static void CreateBackend(shared_ptr& backend, string& backend_name); static shared_ptr m_backend; - static string m_backend_name; static mutex m_backend_mutex; }; diff --git a/ngraph_bridge/deassign_clusters.cc b/ngraph_bridge/deassign_clusters.cc index 621ac483b..c30f65c28 100644 --- a/ngraph_bridge/deassign_clusters.cc +++ b/ngraph_bridge/deassign_clusters.cc @@ -32,7 +32,7 @@ #include "deassign_clusters.h" #include "log.h" #include "mark_for_clustering.h" -#include "utils.h" +#include "tf_utils.h" using namespace std; @@ -121,7 +121,7 @@ static void MaybeLogPlacement(const Graph* graph) { // log the ops gets deassigned std::cout << "NGTF_SUMMARY: Op_deassigned: "; - util::PrintNodeHistogram(deassigned_histogram); + tf_utils::PrintNodeHistogram(deassigned_histogram); for (auto kv : final_cluster_map) { int cluster_idx = kv.first; diff --git a/ngraph_bridge/encapsulate_clusters.cc b/ngraph_bridge/encapsulate_clusters.cc index c7552ae25..833d374bb 100644 --- a/ngraph_bridge/encapsulate_clusters.cc +++ b/ngraph_bridge/encapsulate_clusters.cc @@ -42,7 +42,7 @@ #include "log.h" #include "mark_for_clustering.h" #include "ngraph_builder.h" -#include "utils.h" +#include "tf_utils.h" #include "version.h" using namespace std; @@ -97,7 +97,7 @@ Status EncapsulateClusters( TF_RETURN_IF_ERROR(ConvertGraphDefToGraph( opts, *ClusterManager::GetClusterGraph(cluster_idx), &g)); - util::DumpTFGraph(&g, cluster_idx, "ngraph_cluster_"); + tf_utils::DumpTFGraph(&g, cluster_idx, "ngraph_cluster_"); } } diff --git a/ngraph_bridge/executable.cc b/ngraph_bridge/executable.cc index 476bc4c36..071aa32d3 100644 --- a/ngraph_bridge/executable.cc +++ b/ngraph_bridge/executable.cc @@ -130,10 +130,10 @@ Executable::Executable(shared_ptr func, string device) InferenceEngine::Core ie; std::map options; - if (util::DumpAllGraphs()) { + if (utils::DumpAllGraphs()) { auto& name = m_function->get_friendly_name(); m_network.serialize(name + ".xml", name + ".bin"); - util::DumpNGGraph(func, name + "_executable"); + utils::DumpNGGraph(func, name + "_executable"); if (m_device == "CPU") { options[InferenceEngine::PluginConfigParams::KEY_DUMP_EXEC_GRAPH_AS_DOT] = name + "_IE_" + m_device; diff --git a/ngraph_bridge/kernels/ngraph_encapsulate_op.cc b/ngraph_bridge/kernels/ngraph_encapsulate_op.cc index 7e4310cef..a78f8a7bc 100644 --- a/ngraph_bridge/kernels/ngraph_encapsulate_op.cc +++ b/ngraph_bridge/kernels/ngraph_encapsulate_op.cc @@ -35,6 +35,7 @@ #include "ngraph_bridge/log.h" #include "ngraph_bridge/mark_for_clustering.h" #include "ngraph_bridge/ngraph_builder.h" +#include "ngraph_bridge/tf_utils.h" #include "ngraph_bridge/timer.h" #include "ngraph_bridge/utils.h" @@ -95,7 +96,6 @@ NGraphEncapsulateOp::NGraphEncapsulateOp(OpKernelConstruction* ctx) OP_REQUIRES_OK(ctx, ctx->GetAttr("ngraph_cluster", &m_cluster_id)); std::ostringstream oss; oss << "Encapsulate_" << m_cluster_id << ": " << name(); - NG_TRACE(oss.str(), name(), ""); NGRAPH_VLOG(1) << "NGraphEncapsulateOp: " << m_cluster_id << " Name: " << name(); @@ -190,7 +190,6 @@ NGraphEncapsulateOp::NGraphEncapsulateOp(OpKernelConstruction* ctx) NGraphEncapsulateOp::~NGraphEncapsulateOp() { std::ostringstream oss; oss << "Destroy Encapsulate_" << m_cluster_id << ": " << name(); - NG_TRACE(oss.str(), name(), ""); NGRAPH_VLOG(2) << "~NGraphEncapsulateOp::" << name(); m_ng_exec_map.clear(); } @@ -199,7 +198,6 @@ void NGraphEncapsulateOp::Compute(OpKernelContext* ctx) { NGRAPH_VLOG(1) << "Compute using executor " << name(); std::ostringstream oss; oss << "Execute: Encapsulate_" << m_cluster_id << ": " << name(); - NG_TRACE(oss.str(), name(), ""); NGRAPH_VLOG(4) << "NGraphEncapsulateOp::Compute starting for cluster " << m_cluster_id; @@ -212,24 +210,21 @@ void NGraphEncapsulateOp::Compute(OpKernelContext* ctx) { std::vector tf_input_tensors; std::shared_ptr ng_exec; int step_id; - { - NG_TRACE("FunctionMaybeCreate", name(), ""); - for (int i = 0; i < ctx->num_inputs(); i++) { - tf_input_tensors.push_back(ctx->input(i)); - } + for (int i = 0; i < ctx->num_inputs(); i++) { + tf_input_tensors.push_back(ctx->input(i)); + } - step_id = ctx->step_id(); + step_id = ctx->step_id(); - // Get ngraph executable and inputs information - OP_REQUIRES_OK(ctx, GetExecutable(tf_input_tensors, ng_exec)); + // Get ngraph executable and inputs information + OP_REQUIRES_OK(ctx, GetExecutable(tf_input_tensors, ng_exec)); - NGRAPH_VLOG(1) << " Step_ID: " << step_id; - NGRAPH_VLOG(4) - << "NGraphEncapsulateOp::Compute got ngraph executable for cluster " - << m_cluster_id; + NGRAPH_VLOG(1) << " Step_ID: " << step_id; + NGRAPH_VLOG(4) + << "NGraphEncapsulateOp::Compute got ngraph executable for cluster " + << m_cluster_id; - time_func_create_or_lookup = function_lookup_or_create.ElapsedInMS(); - } + time_func_create_or_lookup = function_lookup_or_create.ElapsedInMS(); NGRAPH_VLOG(4) << "NGraphEncapsulateOp::Compute got graph for cluster " << m_cluster_id; @@ -237,24 +232,20 @@ void NGraphEncapsulateOp::Compute(OpKernelContext* ctx) { Timer create_or_lookup_tensors; vector> ng_inputs; int ng_input_tensor_size_in_bytes = 0; - { - NG_TRACE("Input: maybe create", name(), ""); - // Allocate tensors for input arguments. - for (int i = 0; i < tf_input_tensors.size(); i++) { - ngraph::Shape ng_shape(tf_input_tensors[i].shape().dims()); - for (int j = 0; j < tf_input_tensors[i].shape().dims(); ++j) { - ng_shape[j] = tf_input_tensors[i].shape().dim_size(j); - } - ngraph::element::Type ng_element_type; - OP_REQUIRES_OK(ctx, util::TFDataTypeToNGraphElementType( - tf_input_tensors[i].dtype(), &ng_element_type)); - - auto backend = BackendManager::GetBackend(); - std::shared_ptr ng_tensor = - make_shared(ng_element_type, ng_shape, - tf_input_tensors[i].data()); - ng_inputs.push_back(ng_tensor); + // Allocate tensors for input arguments. + for (int i = 0; i < tf_input_tensors.size(); i++) { + ngraph::Shape ng_shape(tf_input_tensors[i].shape().dims()); + for (int j = 0; j < tf_input_tensors[i].shape().dims(); ++j) { + ng_shape[j] = tf_input_tensors[i].shape().dim_size(j); } + ngraph::element::Type ng_element_type; + OP_REQUIRES_OK(ctx, tf_utils::TFDataTypeToNGraphElementType( + tf_input_tensors[i].dtype(), &ng_element_type)); + + auto backend = BackendManager::GetBackend(); + std::shared_ptr ng_tensor = make_shared( + ng_element_type, ng_shape, tf_input_tensors[i].data()); + ng_inputs.push_back(ng_tensor); } NGRAPH_VLOG(4) << "NGraphEncapsulateOp::Compute allocated argument tensors " @@ -291,9 +282,9 @@ void NGraphEncapsulateOp::Compute(OpKernelContext* ctx) { // expected. ngraph::element::Type expected_elem_type; auto ng_element_type = ng_element->get_element_type(); - OP_REQUIRES_OK( - ctx, util::TFDataTypeToNGraphElementType(ctx->expected_output_dtype(i), - &expected_elem_type)); + OP_REQUIRES_OK(ctx, + tf_utils::TFDataTypeToNGraphElementType( + ctx->expected_output_dtype(i), &expected_elem_type)); OP_REQUIRES( ctx, ng_element_type == expected_elem_type, errors::Internal("Element type inferred by nGraph does not match " @@ -309,24 +300,20 @@ void NGraphEncapsulateOp::Compute(OpKernelContext* ctx) { // Execute the nGraph function. int time_execute_function; { - NG_TRACE("Execute nGraph", name(), ""); Timer execute_function; - { - NGRAPH_VLOG(4) - << "NGraphEncapsulateOp::Compute call starting for cluster " - << m_cluster_id; - try { - ng_exec->Call(ng_inputs, ng_outputs); - } catch (const std::exception& exp) { - string status_string = "Caught exception while executing cluster " + - to_string(m_cluster_id) + ": " + - string(exp.what()); - OP_REQUIRES(ctx, false, errors::Internal(status_string)); - } catch (...) { - string status_string = "Caught exception while executing cluster " + - to_string(m_cluster_id); - OP_REQUIRES(ctx, false, errors::Internal(status_string)); - } + NGRAPH_VLOG(4) << "NGraphEncapsulateOp::Compute call starting for cluster " + << m_cluster_id; + try { + ng_exec->Call(ng_inputs, ng_outputs); + } catch (const std::exception& exp) { + string status_string = "Caught exception while executing cluster " + + to_string(m_cluster_id) + ": " + + string(exp.what()); + OP_REQUIRES(ctx, false, errors::Internal(status_string)); + } catch (...) { + string status_string = + "Caught exception while executing cluster " + to_string(m_cluster_id); + OP_REQUIRES(ctx, false, errors::Internal(status_string)); } time_execute_function = execute_function.ElapsedInMS(); } @@ -348,7 +335,7 @@ void NGraphEncapsulateOp::Compute(OpKernelContext* ctx) { } long vm, rss; - util::MemoryProfile(vm, rss); + utils::MemoryProfile(vm, rss); NGRAPH_VLOG(1) << "NGRAPH_TF_MEM_PROFILE: OP_ID: " << m_cluster_id << " Step_ID: " << step_id << " Cluster: " << name() << " Input Tensors created: " @@ -395,7 +382,7 @@ Status NGraphEncapsulateOp::GetExecutable( if (m_input_is_static[i]) { static_input_map[i] = &tf_input_tensors[i]; TF_RETURN_IF_ERROR( - util::TensorToStream(signature_ss, tf_input_tensors[i])); + tf_utils::TensorToStream(signature_ss, tf_input_tensors[i])); signature_ss << ";"; } } @@ -411,12 +398,12 @@ Status NGraphEncapsulateOp::GetExecutable( if (it == m_ng_exec_map.end()) { // Measure the current total memory usage long vm, rss, vm0, rss0; - util::MemoryProfile(vm0, rss0); + utils::MemoryProfile(vm0, rss0); NGRAPH_VLOG(1) << "Compilation cache miss: " << m_name; TF_RETURN_IF_ERROR(Builder::TranslateGraph(input_shapes, static_input_map, &m_graph, m_name, ng_function)); - util::DumpNGGraph(ng_function, m_name); + utils::DumpNGGraph(ng_function, m_name); // Evict the cache if the number of elements exceeds the limit std::shared_ptr evicted_ng_exec; @@ -432,7 +419,6 @@ Status NGraphEncapsulateOp::GetExecutable( m_lru.pop_back(); } // cache eviction if cache size greater than cache depth - NG_TRACE("Compile nGraph", m_name, ""); try { ng_exec = backend->Compile(ng_function); } catch (const std::exception& ex) { @@ -444,7 +430,7 @@ Status NGraphEncapsulateOp::GetExecutable( m_lru.push_front(signature); // Memory after - util::MemoryProfile(vm, rss); + utils::MemoryProfile(vm, rss); auto delta_vm_mem = vm - vm0; auto delta_res_mem = rss - rss0; NGRAPH_VLOG(1) << "NGRAPH_TF_CACHE_PROFILE: OP_ID: " << m_cluster_id diff --git a/ngraph_bridge/log.h b/ngraph_bridge/log.h index 79e66788e..6ca76604a 100644 --- a/ngraph_bridge/log.h +++ b/ngraph_bridge/log.h @@ -18,7 +18,6 @@ #include #include -#include "tensorflow/core/lib/core/status.h" #include "tensorflow/core/platform/default/logging.h" #include "tensorflow/core/platform/macros.h" diff --git a/ngraph_bridge/mark_for_clustering.cc b/ngraph_bridge/mark_for_clustering.cc index e3bf4964e..e0db0b5cf 100644 --- a/ngraph_bridge/mark_for_clustering.cc +++ b/ngraph_bridge/mark_for_clustering.cc @@ -18,7 +18,8 @@ #include "api.h" #include "backend_manager.h" #include "default_opset.h" -#include "utils.h" +#include "log.h" +#include "tf_utils.h" using namespace std; @@ -169,32 +170,6 @@ static ConfirmationFunction FusedBatchNormConfirmationFunction() { return cf; }; -// Check if op is supported by backend using is_supported API -Status IsSupportedByBackend( - const Node* node, const shared_ptr op_backend, - const std::map>>& - TFtoNgraphOpMap, - bool& is_supported) { - is_supported = true; - - auto ng_op = TFtoNgraphOpMap.find(node->type_string()); - if (ng_op == TFtoNgraphOpMap.end()) { - return errors::Internal("TF Op is not found in the map: ", - node->type_string()); - } - - // Loop through the ngraph op list to query - for (auto it = ng_op->second.begin(); it != ng_op->second.end(); it++) { - // Pass ngraph node to check if backend supports this op - auto ret = op_backend->IsSupported(**it); - if (!ret) { - is_supported = false; - return Status::OK(); - } - } - return Status::OK(); -} - const std::map& GetAttributeSetters() { // // A map of op types (e.g. "Add") to set_attribute functions. These can be @@ -587,192 +562,6 @@ const TypeConstraintMap& GetTypeConstraintMap() { return type_constraint_map; } -const std::map>>& -GetTFToNgOpMap() { - // Constant Op does not have default Constructor - // in ngraph, so passing a dummy node - auto constant = - opset::Constant::create(ngraph::element::f32, ngraph::Shape{}, {2.0f}); - // Map:: TF ops to NG Ops to track if all the Ngraph ops - // 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()}}, - {"Acos", {std::make_shared()}}, - {"Acosh", {std::make_shared()}}, - {"Add", {std::make_shared()}}, - {"AddN", {std::make_shared()}}, - {"AddV2", {std::make_shared()}}, - {"Any", {std::make_shared(), constant}}, - {"All", {std::make_shared(), constant}}, - {"ArgMax", - {std::make_shared(), std::make_shared(), - constant}}, - {"ArgMin", - {std::make_shared(), std::make_shared(), - constant}}, - {"Asin", {std::make_shared()}}, - {"Asinh", {std::make_shared()}}, - {"Atan", {std::make_shared()}}, - {"Atanh", {std::make_shared()}}, - {"AvgPool", {std::make_shared()}}, - {"BiasAdd", - {constant, std::make_shared(), - std::make_shared()}}, - {"Cast", {std::make_shared()}}, - {"Ceil", {std::make_shared()}}, - {"ConcatV2", {std::make_shared()}}, - {"Const", {constant}}, - {"Conv2D", - {std::make_shared(), - std::make_shared()}}, - {"Conv2DBackpropInput", - {std::make_shared(), - std::make_shared(), constant}}, - {"Conv3D", - {constant, std::make_shared(), - std::make_shared()}}, - {"Cos", {std::make_shared()}}, - {"Cosh", {std::make_shared()}}, - {"Cumsum", {std::make_shared()}}, - {"DepthToSpace", {std::make_shared()}}, - {"DepthwiseConv2dNative", - {std::make_shared(), constant}}, - {"Equal", {std::make_shared()}}, - {"Exp", {std::make_shared()}}, - {"ExpandDims", {std::make_shared()}}, - {"Fill", {constant, std::make_shared()}}, - {"Floor", {std::make_shared()}}, - {"FloorDiv", - {std::make_shared(), std::make_shared(), - std::make_shared()}}, - {"FloorMod", {std::make_shared()}}, - {"FusedBatchNorm", {std::make_shared()}}, - {"FusedBatchNormV2", - {constant, std::make_shared(), - std::make_shared()}}, - {"FusedBatchNormV3", - {constant, std::make_shared(), - std::make_shared()}}, - {"Gather", {constant, std::make_shared()}}, - {"GatherV2", {constant, std::make_shared()}}, - {"_FusedConv2D", - {std::make_shared(), constant, - std::make_shared(), std::make_shared(), - std::make_shared(), - std::make_shared()}}, - {"_FusedMatMul", - {std::make_shared(), std::make_shared(), - std::make_shared(), constant, - 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", - {constant, 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()}}, - {"Log1p", - {constant, std::make_shared(), - std::make_shared()}}, - {"LogicalAnd", {std::make_shared()}}, - {"LogicalNot", {std::make_shared()}}, - {"LogicalOr", {std::make_shared()}}, - {"LRN", {std::make_shared()}}, - {"MatMul", {std::make_shared()}}, - {"Max", {std::make_shared(), constant}}, - {"Maximum", {std::make_shared()}}, - {"MaxPool", - {constant, std::make_shared(), - std::make_shared()}}, - {"MaxPool3D", - {constant, std::make_shared(), - std::make_shared()}}, - {"Mean", {std::make_shared(), constant}}, - {"Min", {std::make_shared(), constant}}, - {"Minimum", {std::make_shared()}}, - {"MirrorPad", {constant, std::make_shared()}}, - {"Mul", {std::make_shared()}}, - {"Mod", {std::make_shared()}}, - {"Neg", {std::make_shared()}}, - {"NotEqual", {std::make_shared()}}, - {"NonMaxSuppressionV2", - {std::make_shared(), constant, - std::make_shared(), - std::make_shared()}}, - {"OneHot", {std::make_shared(), constant}}, - {"Pack", - {constant, std::make_shared(), - std::make_shared()}}, - {"Pad", {constant, std::make_shared()}}, - {"PadV2", {constant, std::make_shared()}}, - {"Pow", {std::make_shared()}}, - {"Prod", {std::make_shared(), constant}}, - {"Range", {std::make_shared()}}, - {"Rank", {constant}}, - {"RealDiv", {std::make_shared()}}, - {"Reciprocal", {constant, std::make_shared()}}, - {"Relu", {std::make_shared()}}, - {"Relu6", {std::make_shared()}}, - {"Rsqrt", {constant, std::make_shared()}}, - {"Select", {std::make_shared()}}, - {"SelectV2", {std::make_shared()}}, - {"Reshape", {std::make_shared()}}, - {"Shape", {std::make_shared()}}, - {"Sigmoid", {std::make_shared()}}, - {"Sin", {std::make_shared()}}, - {"Sinh", {std::make_shared()}}, - {"Size", {constant}}, - {"Sign", {std::make_shared()}}, - {"Slice", {constant, std::make_shared()}}, - {"Snapshot", {}}, - {"Softmax", {std::make_shared()}}, - {"Softplus", {std::make_shared()}}, - {"SpaceToDepth", {std::make_shared()}}, - {"Split", {std::make_shared(), constant}}, - {"SplitV", {std::make_shared(), constant}}, - {"Sqrt", {std::make_shared()}}, - {"Square", {std::make_shared()}}, - {"SquaredDifference", {std::make_shared()}}, - {"Squeeze", {std::make_shared(), constant}}, - {"StridedSlice", {constant, std::make_shared()}}, - {"Sub", {std::make_shared()}}, - {"Sum", {std::make_shared(), constant}}, - {"Tan", {std::make_shared()}}, - {"Tanh", {std::make_shared()}}, - {"Tile", {std::make_shared()}}, - {"TopKV2", {std::make_shared(), constant}}, - {"Transpose", {std::make_shared()}}, - {"Where", - {std::make_shared(), - std::make_shared()}}, - {"Xdivy", - {constant, std::make_shared(), - std::make_shared(), - std::make_shared()}}, - {"Unpack", {constant, std::make_shared()}}, - {"ZerosLike", {constant}}, - {"NoOp", {}}, - }; - - return TFtoNgraphOpMap; -} - // // Main entry point for the marking pass. // @@ -787,9 +576,6 @@ Status MarkForClustering(Graph* graph, const std::map& set_attributes_map = GetAttributeSetters(); - const std::map>>& - TFtoNgraphOpMap = GetTFToNgOpMap(); - // // 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 @@ -887,16 +673,12 @@ Status MarkForClustering(Graph* graph, } // Check if op is supported by backend - bool is_supported = false; - TF_RETURN_IF_ERROR(IsSupportedByBackend(node, op_backend, TFtoNgraphOpMap, - is_supported)); - + bool is_supported = op_backend->IsSupported(node->type_string().c_str()); if (!is_supported) { - string backend; - BackendManager::GetBackendName(backend); NGRAPH_VLOG(5) << "TF Op " << node->name() << " of type " << node->type_string() - << " is not supported by backend: " << backend; + << " is not supported by backend: " + << op_backend->Name(); break; } @@ -920,11 +702,11 @@ Status MarkForClustering(Graph* graph, std::cout << "\n=============New sub-graph logs=============\n"; // print summary for nodes failed to be marked std::cout << "NGTF_SUMMARY: Op_not_supported: "; - util::PrintNodeHistogram(no_support_histogram); + tf_utils::PrintNodeHistogram(no_support_histogram); std::cout << "NGTF_SUMMARY: Op_failed_confirmation: "; - util::PrintNodeHistogram(fail_confirmation_histogram); + tf_utils::PrintNodeHistogram(fail_confirmation_histogram); std::cout << "NGTF_SUMMARY: Op_failed_type_constraint: "; - util::PrintNodeHistogram(fail_constraint_histogram); + tf_utils::PrintNodeHistogram(fail_constraint_histogram); } for (auto node : nodes_marked_for_clustering) { diff --git a/ngraph_bridge/mark_for_clustering.h b/ngraph_bridge/mark_for_clustering.h index 64a41424f..563b7d122 100644 --- a/ngraph_bridge/mark_for_clustering.h +++ b/ngraph_bridge/mark_for_clustering.h @@ -52,8 +52,5 @@ 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_builder.cc b/ngraph_bridge/ngraph_builder.cc index 4a569315a..29d285e1c 100644 --- a/ngraph_bridge/ngraph_builder.cc +++ b/ngraph_bridge/ngraph_builder.cc @@ -33,6 +33,7 @@ #include "ngraph_builder.h" #include "ngraph_conversions.h" #include "pass/transpose_sinking.h" +#include "tf_utils.h" #include "utils.h" using tensorflow::int32; @@ -315,7 +316,7 @@ static Status GetStaticInputNode( const std::vector& static_input_map, DataType dt, ng::Output& node_) { ng::element::Type type; - TF_RETURN_IF_ERROR(util::TFDataTypeToNGraphElementType(dt, &type)); + TF_RETURN_IF_ERROR(tf_utils::TFDataTypeToNGraphElementType(dt, &type)); switch (dt) { case DataType::DT_FLOAT: { std::vector vec_float; @@ -483,7 +484,8 @@ static Status MakeConstOp(const Node* op, ng::element::Type et, TensorShape const_shape(shape_proto); ng::Shape ng_shape; - TF_RETURN_IF_ERROR(util::TFTensorShapeToNGraphShape(const_shape, &ng_shape)); + TF_RETURN_IF_ERROR( + tf_utils::TFTensorShapeToNGraphShape(const_shape, &ng_shape)); ng_node = ConstructNgNode(op->name(), et, ng_shape, const_values); @@ -675,7 +677,7 @@ static Status TranslateArgMinMax( TF_RETURN_IF_ERROR(GetNodeAttr(op->attrs(), "output_type", &dtype)); ng::element::Type ng_et; - TF_RETURN_IF_ERROR(util::TFDataTypeToNGraphElementType(dtype, &ng_et)); + TF_RETURN_IF_ERROR(tf_utils::TFDataTypeToNGraphElementType(dtype, &ng_et)); auto ng_k = ConstructNgNode( op->name(), ng::element::i64, ng::Shape{}, std::vector({1})); @@ -826,7 +828,7 @@ static Status TranslateCastOp(const Node* op, const std::vector&, TF_RETURN_IF_ERROR(GetNodeAttr(op->attrs(), "DstT", &dtype)); ng::element::Type ng_et; - TF_RETURN_IF_ERROR(util::TFDataTypeToNGraphElementType(dtype, &ng_et)); + TF_RETURN_IF_ERROR(tf_utils::TFDataTypeToNGraphElementType(dtype, &ng_et)); try { SaveNgOp(ng_op_map, op->name(), @@ -2099,7 +2101,7 @@ static Status TranslateRangeOp( DataType step_type = op->input_type(2); ng::element::Type out_type; TF_RETURN_IF_ERROR( - util::TFDataTypeToNGraphElementType(op->output_type(0), &out_type)); + tf_utils::TFDataTypeToNGraphElementType(op->output_type(0), &out_type)); ng::Output start_node, stop_node, step_node; TF_RETURN_IF_ERROR( GetStaticInputNode(op, 0, static_input_map, start_type, start_node)); @@ -2206,7 +2208,7 @@ static Status TranslateShapeOp(const Node* op, TF_RETURN_IF_ERROR(GetNodeAttr(op->attrs(), "out_type", &dtype)); ng::element::Type type; - TF_RETURN_IF_ERROR(util::TFDataTypeToNGraphElementType(dtype, &type)); + TF_RETURN_IF_ERROR(tf_utils::TFDataTypeToNGraphElementType(dtype, &type)); // default output_type = element::i64 SaveNgOp(ng_op_map, op->name(), @@ -2224,7 +2226,7 @@ static Status TranslateSizeOp(const Node* op, const std::vector&, // Size has an attribute to specify output, int32 or int64 ng::element::Type type; - TF_RETURN_IF_ERROR(util::TFDataTypeToNGraphElementType(dtype, &type)); + TF_RETURN_IF_ERROR(tf_utils::TFDataTypeToNGraphElementType(dtype, &type)); auto ng_input_shape = ng_input.get_shape(); int64 result = 1; @@ -2895,11 +2897,11 @@ Status Builder::TranslateGraph( } ng::element::Type ng_et; - TF_RETURN_IF_ERROR(util::TFDataTypeToNGraphElementType(dtype, &ng_et)); + TF_RETURN_IF_ERROR(tf_utils::TFDataTypeToNGraphElementType(dtype, &ng_et)); ng::Shape ng_shape; TF_RETURN_IF_ERROR( - util::TFTensorShapeToNGraphShape(inputs[index], &ng_shape)); + tf_utils::TFTensorShapeToNGraphShape(inputs[index], &ng_shape)); string prov_tag; GetNodeAttr(parm->attrs(), "_prov_tag", &prov_tag); @@ -2979,10 +2981,10 @@ Status Builder::TranslateGraph( // { ngraph::pass::Manager passes; - if (util::GetEnv("NGRAPH_TF_CONSTANT_FOLDING") == "1") { + if (utils::GetEnv("NGRAPH_TF_CONSTANT_FOLDING") == "1") { passes.register_pass(); } - if (util::GetEnv("NGRAPH_TF_TRANSPOSE_SINKING") != "0") { + if (utils::GetEnv("NGRAPH_TF_TRANSPOSE_SINKING") != "0") { passes.register_pass(); } passes.run_passes(ng_function); diff --git a/ngraph_bridge/ngraph_rewrite_pass.cc b/ngraph_bridge/ngraph_rewrite_pass.cc index 21045352f..b958d2868 100644 --- a/ngraph_bridge/ngraph_rewrite_pass.cc +++ b/ngraph_bridge/ngraph_rewrite_pass.cc @@ -29,7 +29,7 @@ #include "log.h" #include "mark_for_clustering.h" #include "ngraph_rewrite_pass.h" -#include "utils.h" +#include "tf_utils.h" using namespace std; @@ -57,14 +57,14 @@ Status NGraphRewritePass::Rewrite( // runs of this pass. int idx = FreshIndex(); // If requested, dump unmarked graphs. - util::DumpTFGraph(graph, idx, "unmarked"); + tf_utils::DumpTFGraph(graph, idx, "unmarked"); // If ngraph is disabled via ngraph_bridge api or NGRAPH_TF_DISABLE is set // we will not do anything; all subsequent // passes become a no-op. bool ngraph_not_enabled = (!api::IsEnabled()) || (std::getenv("NGRAPH_TF_DISABLE") != nullptr); - bool already_processed = util::IsAlreadyProcessed(graph); + bool already_processed = tf_utils::IsAlreadyProcessed(graph); if (!already_processed && ngraph_not_enabled) { NGRAPH_VLOG(0) << "NGraph is available but disabled."; } @@ -80,15 +80,15 @@ Status NGraphRewritePass::Rewrite( // 1. Mark for clustering then, if requested, dump the graphs. TF_RETURN_IF_ERROR(MarkForClustering(graph, skip_these_nodes)); - util::DumpTFGraph(graph, idx, "marked"); + tf_utils::DumpTFGraph(graph, idx, "marked"); // 2. Assign clusters then, if requested, dump the graphs. TF_RETURN_IF_ERROR(AssignClusters(graph)); - util::DumpTFGraph(graph, idx, "clustered"); + tf_utils::DumpTFGraph(graph, idx, "clustered"); // 3. Deassign trivial clusters then, if requested, dump the graphs. TF_RETURN_IF_ERROR(DeassignClusters(graph)); - util::DumpTFGraph(graph, idx, "declustered"); + tf_utils::DumpTFGraph(graph, idx, "declustered"); // 4. Encapsulate clusters then, if requested, dump the graphs. auto status = EncapsulateClusters(graph, idx, config_map); @@ -96,7 +96,7 @@ Status NGraphRewritePass::Rewrite( return status; } - util::DumpTFGraph(graph, idx, "encapsulated"); + tf_utils::DumpTFGraph(graph, idx, "encapsulated"); return Status::OK(); } @@ -115,4 +115,4 @@ Status NGraphRewritePass::Run(const GraphOptimizationPassOptions& options) { REGISTER_OPTIMIZATION(OptimizationPassRegistry::POST_REWRITE_FOR_EXEC, 0, ngraph_bridge::NGraphRewritePass); #endif -} // namespace tensorflow \ No newline at end of file +} // namespace tensorflow diff --git a/ngraph_bridge/pass/transpose_sinking.cc b/ngraph_bridge/pass/transpose_sinking.cc index de82f77d4..ed8f500bd 100644 --- a/ngraph_bridge/pass/transpose_sinking.cc +++ b/ngraph_bridge/pass/transpose_sinking.cc @@ -436,8 +436,8 @@ bool TransposeSinking::run_on_function(shared_ptr f) { set> transposes_to_delete; unordered_map orig_result_out_shape; - if (util::DumpAllGraphs()) { - util::DumpNGGraph(f, f->get_friendly_name() + "_before_TS"); + if (utils::DumpAllGraphs()) { + utils::DumpNGGraph(f, f->get_friendly_name() + "_before_TS"); } // STEP 1 : Sink or Swim transposes away for op clusters @@ -489,8 +489,8 @@ bool TransposeSinking::run_on_function(shared_ptr f) { orig_result_out_shape[r->get_name()]); } - if (util::DumpAllGraphs()) { - util::DumpNGGraph(f, f->get_friendly_name() + "_after_TS"); + if (utils::DumpAllGraphs()) { + utils::DumpNGGraph(f, f->get_friendly_name() + "_after_TS"); } return true; } diff --git a/ngraph_bridge/tf_utils.cc b/ngraph_bridge/tf_utils.cc new file mode 100644 index 000000000..6b12d3dba --- /dev/null +++ b/ngraph_bridge/tf_utils.cc @@ -0,0 +1,224 @@ +/******************************************************************************* + * Copyright 2017-2021 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 +#include +#include +#include + +#include "log.h" +#include "tf_utils.h" +#include "utils.h" +#include "version.h" + +using namespace std; + +namespace tensorflow { +namespace ngraph_bridge { +namespace tf_utils { + +template +static void TensorDataToStream(std::ostream& ostream, int64 n_elements, + const char* data) { + const T* data_T = reinterpret_cast(data); + for (size_t i = 0; i < n_elements; i++) { + ostream << data_T[i] << ","; + } +} + +Status TensorToStream(std::ostream& ostream, const Tensor& tensor) { + const char* data = tensor.tensor_data().data(); + int64 n_elements = tensor.NumElements(); + switch (tensor.dtype()) { + case DT_HALF: + TensorDataToStream(ostream, n_elements, data); + break; + case DT_FLOAT: + TensorDataToStream(ostream, n_elements, data); + break; + case DT_DOUBLE: + TensorDataToStream(ostream, n_elements, data); + break; + case DT_UINT32: + TensorDataToStream(ostream, n_elements, data); + break; + case DT_INT32: + TensorDataToStream(ostream, n_elements, data); + break; + case DT_UINT8: + case DT_QUINT8: + TensorDataToStream(ostream, n_elements, data); + break; + case DT_UINT16: + case DT_QUINT16: + TensorDataToStream(ostream, n_elements, data); + break; + case DT_INT8: + case DT_QINT8: + TensorDataToStream(ostream, n_elements, data); + break; + case DT_INT16: + case DT_QINT16: + TensorDataToStream(ostream, n_elements, data); + break; + case DT_UINT64: + TensorDataToStream(ostream, n_elements, data); + break; + case DT_INT64: + TensorDataToStream(ostream, n_elements, data); + break; + case DT_BOOL: + TensorDataToStream(ostream, n_elements, data); + break; + case DT_BFLOAT16: + return errors::Internal( + "TensorToStream got data type bfloat16. No compatible standard C++ " + "data type."); + break; + default: + return errors::Internal("TensorToStream got unsupported data type ", + DataType_Name(tensor.dtype())); + break; + } + return Status::OK(); +} + +Status TFDataTypeToNGraphElementType(DataType tf_dt, + ngraph::element::Type* ng_et) { + switch (tf_dt) { + case DataType::DT_FLOAT: + *ng_et = ngraph::element::f32; + break; + case DataType::DT_DOUBLE: + *ng_et = ngraph::element::f64; + break; + case DataType::DT_INT32: + *ng_et = ngraph::element::i32; + break; + case DataType::DT_UINT8: + *ng_et = ngraph::element::u8; + break; + case DataType::DT_INT8: + *ng_et = ngraph::element::i8; + break; + case DataType::DT_UINT16: + *ng_et = ngraph::element::u16; + break; + case DataType::DT_INT64: + *ng_et = ngraph::element::i64; + break; + case DataType::DT_UINT32: + *ng_et = ngraph::element::u32; + break; + case DataType::DT_UINT64: + *ng_et = ngraph::element::u64; + break; + case DataType::DT_BOOL: + *ng_et = ngraph::element::boolean; + break; + case DataType::DT_QINT8: + *ng_et = ngraph::element::i8; + break; + case DataType::DT_QUINT8: + *ng_et = ngraph::element::u8; + break; + case DataType::DT_QINT32: + *ng_et = ngraph::element::i32; + break; + case DataType::DT_BFLOAT16: + *ng_et = ngraph::element::bf16; + break; + case DataType::DT_HALF: + *ng_et = ngraph::element::f16; + break; + default: + return errors::Unimplemented("Unsupported TensorFlow data type: ", + DataType_Name(tf_dt)); + } + return Status::OK(); +} + +Status TFTensorShapeToNGraphShape(const TensorShape& tf_shape, + ngraph::Shape* ng_shape) { + for (int i = 0; i < tf_shape.dims(); i++) { + if (tf_shape.dim_size(i) < 0) { + return errors::InvalidArgument( + "TensorFlow shape has a negative dimension size"); + } + } + + *ng_shape = ngraph::Shape(tf_shape.dims()); + for (int i = 0; i < tf_shape.dims(); i++) { + (*ng_shape)[i] = tf_shape.dim_size(i); + } + + return Status::OK(); +} + +void PrintNodeHistogram(const std::unordered_map& histogram, + bool sorted) { + int histogram_size = histogram.size(); + if (histogram_size == 0) { + std::cout << "None"; + } else { + vector> vec(begin(histogram), end(histogram)); + if (sorted) { + sort(begin(vec), end(vec), + [](const pair& a, const pair& b) { + // descending sort + return a.second > b.second; + }); + } + + for (auto node : vec) { + bool endelem = node == vec.back(); + std::cout << " " << node.first << " -> " << node.second + << (endelem ? " " : ","); + } + } + std::cout << std::endl; +} + +void DumpTFGraph(tensorflow::Graph* graph, int idx, std::string filename) { + if (!utils::DumpAllGraphs()) { + return; + } + + std::stringstream ss; + ss << filename << "_" << std::setfill('0') << std::setw(4) << idx; + NGRAPH_VLOG(0) << "Dumping TF graph to " << ss.str() + ".pbtxt"; + + GraphDef g_def; + graph->ToGraphDef(&g_def); + + string graph_pb_str; + protobuf::TextFormat::PrintToString(g_def, &graph_pb_str); + std::ofstream ostrm_out(ss.str() + ".pbtxt", std::ios_base::trunc); + ostrm_out << graph_pb_str; +} + +bool IsAlreadyProcessed(Graph* g) { + // TODO: place a dummy node as a marker + // Current method may fail when graph has no encapsulates after first pass + for (Node* node : g->nodes()) { + if (node->type_string() == "_nGraphEncapsulate") return true; + } + return false; +} + +} // namespace tf_utils +} // namespace ngraph_bridge +} // namespace tensorflow diff --git a/ngraph_bridge/tf_utils.h b/ngraph_bridge/tf_utils.h new file mode 100644 index 000000000..6790cd56c --- /dev/null +++ b/ngraph_bridge/tf_utils.h @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright 2017-2021 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. + *******************************************************************************/ + +#pragma once + +#include +#include +#include + +#include "tensorflow/core/common_runtime/dma_helper.h" +#include "tensorflow/core/common_runtime/optimization_registry.h" +#include "tensorflow/core/framework/op_kernel.h" +#include "tensorflow/core/graph/graph.h" +#include "tensorflow/core/platform/tensor_coding.h" +#include "tensorflow/core/util/saved_tensor_slice_util.h" + +#include "ngraph/ngraph.hpp" + +using namespace std; + +namespace tensorflow { +namespace ngraph_bridge { +namespace tf_utils { + +bool IsAlreadyProcessed(Graph* g); + +// Descending sort the map based on the value +void PrintNodeHistogram(const std::unordered_map&, + bool sorted = true); + +Status TensorToStream(std::ostream& ostream, const Tensor& tensor); + +// Converts a TensorFlow DataType to an nGraph element::Type. Returns +// errors::Unimplemented if the element type is not supported by nGraph +// Core. Otherwise returns Status::OK(). +Status TFDataTypeToNGraphElementType(DataType tf_dt, + ngraph::element::Type* ng_et); + +// Converts a TensorFlow TensorShape to an nGraph Shape. Requires that none of +// the dimension lengths in tf_shape are negative. +Status TFTensorShapeToNGraphShape(const TensorShape& tf_shape, + ngraph::Shape* ng_shape); + +// Dump TF graphs in .pbtxt format +void DumpTFGraph(tensorflow::Graph* graph, int idx, string filename_prefix); + +} // namespace tf_utils +} // namespace ngraph_bridge +} // namespace tensorflow diff --git a/ngraph_bridge/utils.cc b/ngraph_bridge/utils.cc index 119770b7d..7e317756c 100644 --- a/ngraph_bridge/utils.cc +++ b/ngraph_bridge/utils.cc @@ -19,16 +19,6 @@ #include #include -#include "tensorflow/core/common_runtime/dma_helper.h" -#include "tensorflow/core/common_runtime/optimization_registry.h" -#include "tensorflow/core/framework/attr_value_util.h" -#include "tensorflow/core/framework/graph.pb.h" -#include "tensorflow/core/framework/node_def_util.h" -#include "tensorflow/core/graph/graph.h" -#include "tensorflow/core/lib/strings/str_util.h" -#include "tensorflow/core/platform/default/logging.h" -#include "tensorflow/core/platform/protobuf.h" - #include "utils.h" #include "version.h" @@ -36,169 +26,7 @@ using namespace std; namespace tensorflow { namespace ngraph_bridge { -namespace util { - -template -static void TensorDataToStream(std::ostream& ostream, int64 n_elements, - const char* data) { - const T* data_T = reinterpret_cast(data); - for (size_t i = 0; i < n_elements; i++) { - ostream << data_T[i] << ","; - } -} - -Status TensorToStream(std::ostream& ostream, const Tensor& tensor) { - const char* data = tensor.tensor_data().data(); - int64 n_elements = tensor.NumElements(); - switch (tensor.dtype()) { - case DT_HALF: - TensorDataToStream(ostream, n_elements, data); - break; - case DT_FLOAT: - TensorDataToStream(ostream, n_elements, data); - break; - case DT_DOUBLE: - TensorDataToStream(ostream, n_elements, data); - break; - case DT_UINT32: - TensorDataToStream(ostream, n_elements, data); - break; - case DT_INT32: - TensorDataToStream(ostream, n_elements, data); - break; - case DT_UINT8: - case DT_QUINT8: - TensorDataToStream(ostream, n_elements, data); - break; - case DT_UINT16: - case DT_QUINT16: - TensorDataToStream(ostream, n_elements, data); - break; - case DT_INT8: - case DT_QINT8: - TensorDataToStream(ostream, n_elements, data); - break; - case DT_INT16: - case DT_QINT16: - TensorDataToStream(ostream, n_elements, data); - break; - case DT_UINT64: - TensorDataToStream(ostream, n_elements, data); - break; - case DT_INT64: - TensorDataToStream(ostream, n_elements, data); - break; - case DT_BOOL: - TensorDataToStream(ostream, n_elements, data); - break; - case DT_BFLOAT16: - return errors::Internal( - "TensorToStream got data type bfloat16. No compatible standard C++ " - "data type."); - break; - default: - return errors::Internal("TensorToStream got unsupported data type ", - DataType_Name(tensor.dtype())); - break; - } - return Status::OK(); -} - -Status TFDataTypeToNGraphElementType(DataType tf_dt, - ngraph::element::Type* ng_et) { - switch (tf_dt) { - case DataType::DT_FLOAT: - *ng_et = ngraph::element::f32; - break; - case DataType::DT_DOUBLE: - *ng_et = ngraph::element::f64; - break; - case DataType::DT_INT32: - *ng_et = ngraph::element::i32; - break; - case DataType::DT_UINT8: - *ng_et = ngraph::element::u8; - break; - case DataType::DT_INT8: - *ng_et = ngraph::element::i8; - break; - case DataType::DT_UINT16: - *ng_et = ngraph::element::u16; - break; - case DataType::DT_INT64: - *ng_et = ngraph::element::i64; - break; - case DataType::DT_UINT32: - *ng_et = ngraph::element::u32; - break; - case DataType::DT_UINT64: - *ng_et = ngraph::element::u64; - break; - case DataType::DT_BOOL: - *ng_et = ngraph::element::boolean; - break; - case DataType::DT_QINT8: - *ng_et = ngraph::element::i8; - break; - case DataType::DT_QUINT8: - *ng_et = ngraph::element::u8; - break; - case DataType::DT_QINT32: - *ng_et = ngraph::element::i32; - break; - case DataType::DT_BFLOAT16: - *ng_et = ngraph::element::bf16; - break; - case DataType::DT_HALF: - *ng_et = ngraph::element::f16; - break; - default: - return errors::Unimplemented("Unsupported TensorFlow data type: ", - DataType_Name(tf_dt)); - } - return Status::OK(); -} - -Status TFTensorShapeToNGraphShape(const TensorShape& tf_shape, - ngraph::Shape* ng_shape) { - for (int i = 0; i < tf_shape.dims(); i++) { - if (tf_shape.dim_size(i) < 0) { - return errors::InvalidArgument( - "TensorFlow shape has a negative dimension size"); - } - } - - *ng_shape = ngraph::Shape(tf_shape.dims()); - for (int i = 0; i < tf_shape.dims(); i++) { - (*ng_shape)[i] = tf_shape.dim_size(i); - } - - return Status::OK(); -} - -void PrintNodeHistogram(const std::unordered_map& histogram, - bool sorted) { - int histogram_size = histogram.size(); - if (histogram_size == 0) { - std::cout << "None"; - } else { - vector> vec(begin(histogram), end(histogram)); - if (sorted) { - sort(begin(vec), end(vec), - [](const pair& a, const pair& b) { - // descending sort - return a.second > b.second; - }); - } - - for (auto node : vec) { - bool endelem = node == vec.back(); - std::cout << " " << node.first << " -> " << node.second - << (endelem ? " " : ","); - } - } - std::cout << std::endl; -} +namespace utils { void MemoryProfile(long& vm_usage, long& resident_set) { vm_usage = 0; @@ -223,24 +51,6 @@ void MemoryProfile(long& vm_usage, long& resident_set) { } } -void DumpTFGraph(tensorflow::Graph* graph, int idx, std::string filename) { - if (!DumpAllGraphs()) { - return; - } - - std::stringstream ss; - ss << filename << "_" << std::setfill('0') << std::setw(4) << idx; - NGRAPH_VLOG(0) << "Dumping TF graph to " << ss.str() + ".pbtxt"; - - GraphDef g_def; - graph->ToGraphDef(&g_def); - - string graph_pb_str; - protobuf::TextFormat::PrintToString(g_def, &graph_pb_str); - std::ofstream ostrm_out(ss.str() + ".pbtxt", std::ios_base::trunc); - ostrm_out << graph_pb_str; -} - void DumpNGGraph(std::shared_ptr function, const string filename) { if (!DumpAllGraphs()) { @@ -257,15 +67,6 @@ void DumpNGGraph(std::shared_ptr function, bool DumpAllGraphs() { return GetEnv("NGRAPH_TF_DUMP_GRAPHS") == "1"; } -bool IsAlreadyProcessed(Graph* g) { - // TODO: place a dummy node as a marker - // Current method may fail when graph has no encapsulates after first pass - for (Node* node : g->nodes()) { - if (node->type_string() == "_nGraphEncapsulate") return true; - } - return false; -} - string GetEnv(const char* env) { const char* val = std::getenv(env); if (val == nullptr) { @@ -277,6 +78,6 @@ string GetEnv(const char* env) { void SetEnv(const char* env, const char* val) { setenv(env, val, 1); } -} // namespace util +} // namespace utils } // namespace ngraph_bridge } // namespace tensorflow diff --git a/ngraph_bridge/utils.h b/ngraph_bridge/utils.h index b40f63128..22765f69a 100644 --- a/ngraph_bridge/utils.h +++ b/ngraph_bridge/utils.h @@ -16,59 +16,27 @@ #pragma once +#include #include #include #include -#include "tensorflow/core/common_runtime/dma_helper.h" -#include "tensorflow/core/common_runtime/optimization_registry.h" -#include "tensorflow/core/framework/op_kernel.h" -#include "tensorflow/core/graph/graph.h" -#include "tensorflow/core/platform/tensor_coding.h" -#include "tensorflow/core/util/saved_tensor_slice_util.h" - -#include "ngraph/chrome_trace.hpp" #include "ngraph/ngraph.hpp" #include "log.h" -// Activates event logging until the end of the current code-block scoping; -// Automatically writes log data as soon as the the current scope expires. -#define NG_TRACE(name, category, args) \ - ngraph::event::Duration dx__ { (name), (category), (args) } - using namespace std; namespace tensorflow { namespace ngraph_bridge { -namespace util { - -bool IsAlreadyProcessed(Graph* g); - -// Descending sort the map based on the value -void PrintNodeHistogram(const std::unordered_map&, - bool sorted = true); - -Status TensorToStream(std::ostream& ostream, const Tensor& tensor); - -// Converts a TensorFlow DataType to an nGraph element::Type. Returns -// errors::Unimplemented if the element type is not supported by nGraph -// Core. Otherwise returns Status::OK(). -Status TFDataTypeToNGraphElementType(DataType tf_dt, - ngraph::element::Type* ng_et); - -// Converts a TensorFlow TensorShape to an nGraph Shape. Requires that none of -// the dimension lengths in tf_shape are negative. -Status TFTensorShapeToNGraphShape(const TensorShape& tf_shape, - ngraph::Shape* ng_shape); +namespace utils { // Collect the total memory usage through /proc/self/stat void MemoryProfile(long&, long&); // Check if we're supposed to dump graphs bool DumpAllGraphs(); -// Dump TF graphs in .pbtxt format -void DumpTFGraph(tensorflow::Graph* graph, int idx, string filename_prefix); + // Dump nGraph graphs in .dot format void DumpNGGraph(std::shared_ptr function, const string filename_prefix); @@ -79,6 +47,6 @@ string GetEnv(const char* env); // Set the environment variable env with val void SetEnv(const char* env, const char* val); -} // namespace util +} // namespace utils } // namespace ngraph_bridge } // namespace tensorflow diff --git a/test/graph_rewrites/backend_manager_test.cc b/test/graph_rewrites/backend_manager_test.cc index 1ec9fd80d..c76b5ffc4 100644 --- a/test/graph_rewrites/backend_manager_test.cc +++ b/test/graph_rewrites/backend_manager_test.cc @@ -41,11 +41,10 @@ These tests test the Backend Handling by the bridge. TEST(BackendManager, SetBackend) { auto env_map = StoreEnv({"NGRAPH_TF_BACKEND"}); - ASSERT_OK(BackendManager::SetBackend("CPU")); - string backend; - ASSERT_OK(BackendManager::GetBackendName(backend)); - ASSERT_EQ(backend, "CPU"); - ASSERT_NOT_OK(BackendManager::SetBackend("temp")); + EXPECT_NO_THROW(BackendManager::SetBackend("CPU")); + auto backend = BackendManager::GetBackend(); + ASSERT_EQ(backend->Name(), "CPU"); + EXPECT_ANY_THROW(BackendManager::SetBackend("temp")); // Clean Up // If NGRAPH_TF_BACKEND was set, set it back @@ -53,40 +52,39 @@ TEST(BackendManager, SetBackend) { } // Test GetBackend API -TEST(BackendManager, GetBackendName) { +TEST(BackendManager, GetBackend) { auto env_map = StoreEnv({"NGRAPH_TF_BACKEND"}); - ASSERT_OK(BackendManager::SetBackend("CPU")); - string backend; - ASSERT_OK(BackendManager::GetBackendName(backend)); - ASSERT_EQ(backend, "CPU"); + EXPECT_NO_THROW(BackendManager::SetBackend("CPU")); + auto backend = BackendManager::GetBackend(); + ASSERT_EQ(backend->Name(), "CPU"); // expected ERROR SetBackendUsingEnvVar("DUMMY"); - ASSERT_OK(BackendManager::GetBackendName(backend)); - ASSERT_EQ(backend, "CPU"); + backend = BackendManager::GetBackend(); + ASSERT_EQ(backend->Name(), "CPU"); // set env variable to "" SetBackendUsingEnvVar(""); - ASSERT_OK(BackendManager::GetBackendName(backend)); - ASSERT_EQ(backend, "CPU"); + backend = BackendManager::GetBackend(); + ASSERT_EQ(backend->Name(), "CPU"); // set backend to dummy and env variable to CPU // expected CPU - ASSERT_NOT_OK(BackendManager::SetBackend("DUMMY")); + EXPECT_ANY_THROW(BackendManager::SetBackend("DUMMY")); SetBackendUsingEnvVar("CPU"); - ASSERT_OK(BackendManager::GetBackendName(backend)); - ASSERT_EQ(backend, "CPU"); + backend = BackendManager::GetBackend(); + ASSERT_EQ(backend->Name(), "CPU"); // unset env variable // expected interpreter UnsetBackendUsingEnvVar(); - ASSERT_OK(BackendManager::GetBackendName(backend)); - ASSERT_EQ(backend, "CPU"); + backend = BackendManager::GetBackend(); + ASSERT_EQ(backend->Name(), "CPU"); // Clean up UnsetBackendUsingEnvVar(); - ASSERT_OK(BackendManager::SetBackend("CPU")); + EXPECT_NO_THROW(BackendManager::SetBackend("CPU")); // restore // If NGRAPH_TF_BACKEND was set, set it back RestoreEnv(env_map); diff --git a/test/graph_rewrites/op_by_op_capability_test.cc b/test/graph_rewrites/op_by_op_capability_test.cc index 0856056ee..d5e4435a6 100644 --- a/test/graph_rewrites/op_by_op_capability_test.cc +++ b/test/graph_rewrites/op_by_op_capability_test.cc @@ -60,18 +60,8 @@ TEST(OpByOpCapability, Backend) { auto constant = ngraph::op::Constant::create(ngraph::element::f32, ngraph::Shape{}, {2.0f}); - std::map>> - TFtoNgraphOpMap{ - {"Const", {constant}}, - {"Add", {std::make_shared()}}, - {"Mul", - {std::make_shared(), - std::make_shared()}}, - }; - for (auto node : graph.op_nodes()) { - ASSERT_OK( - IsSupportedByBackend(node, backend, TFtoNgraphOpMap, is_supported)); + is_supported = backend->IsSupported(node->type_string().c_str()); ASSERT_EQ(is_supported, true); } } diff --git a/test/test_thread_safe_queue.cc b/test/test_thread_safe_queue.cc index 3de93c4b6..6cbfc0216 100644 --- a/test/test_thread_safe_queue.cc +++ b/test/test_thread_safe_queue.cc @@ -23,7 +23,6 @@ #include "../examples/cpp/thread_safe_queue.h" #include "gtest/gtest.h" -#include "ngraph_bridge/utils.h" using namespace std; @@ -47,20 +46,15 @@ TEST(ThreadSafeQueue, Simple) { // Create two threads auto consumer = [&]() { while (item_count < 3) { - { - NG_TRACE("Consumer", "Do Wait", ""); - while (consumer_do_wait) { - // cout << "\033[1;32mConsumer waiting\033[0m\n"; - absl::SleepFor(absl::Milliseconds(1)); - } + while (consumer_do_wait) { + // cout << "\033[1;32mConsumer waiting\033[0m\n"; + absl::SleepFor(absl::Milliseconds(1)); } - { - NG_TRACE("Consumer", "Waiting", ""); - consumer_state = WAITING_FOR_ITEM; - // cout << "\033[1;32mWaiting\033[0m" << endl; - queue.GetNextAvailable(); - } + consumer_state = WAITING_FOR_ITEM; + // cout << "\033[1;32mWaiting\033[0m" << endl; + queue.GetNextAvailable(); + // cout << "\033[1;32mGot Item: " << item_count << "\033[0m\n"; item_count++; consumer_state = GOT_ITEM; @@ -73,22 +67,16 @@ TEST(ThreadSafeQueue, Simple) { }; std::thread thread0(consumer); - { - NG_TRACE("Producer", "Waiting", ""); - // Ensure that the consumer is in waiting state - ASSERT_TRUE(consumer_do_wait); + // Ensure that the consumer is in waiting state + ASSERT_TRUE(consumer_do_wait); - consumer_do_wait = false; - while (consumer_state != WAITING_FOR_ITEM) { - absl::SleepFor(absl::Milliseconds(1)); - } + consumer_do_wait = false; + while (consumer_state != WAITING_FOR_ITEM) { + absl::SleepFor(absl::Milliseconds(1)); } // cout << "Now adding an item\n"; - { - NG_TRACE("Producer", "Add", ""); - queue.Add(nullptr); - } + queue.Add(nullptr); // Wait until the consumer has a chance to move forward // cout << "Producer: Waiting for consumer to get ready" << endl; @@ -100,11 +88,8 @@ TEST(ThreadSafeQueue, Simple) { // The consumer is now waiting again until consumer_do_wait is signaled // Add two more items // //cout << "Now adding two items\n"; - { - NG_TRACE("Producer", "Add-2", ""); - queue.Add(nullptr); - queue.Add(nullptr); - } + queue.Add(nullptr); + queue.Add(nullptr); // cout << "Producer: Waiting for consumer to get ready" << endl; diff --git a/test/tf_exec.cpp b/test/tf_exec.cpp index 988249d1a..5da31e018 100644 --- a/test/tf_exec.cpp +++ b/test/tf_exec.cpp @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ +#include #include "gtest/gtest.h" #include "tensorflow/cc/client/client_session.h"