[moco-import] Refine error handling in validate and build (#9149)
author박세희/On-Device Lab(SR)/Principal Engineer/삼성전자 <saehie.park@samsung.com>
Mon, 25 Nov 2019 03:15:24 +0000 (12:15 +0900)
committerGitHub Enterprise <noreply-CODE@samsung.com>
Mon, 25 Nov 2019 03:15:24 +0000 (12:15 +0900)
This will refine error handling way and message in validate and build methods

Signed-off-by: SaeHie Park <saehie.park@samsung.com>
14 files changed:
compiler/moco/import/src/Nodes/BiasAdd.cpp
compiler/moco/import/src/Nodes/Concat.cpp
compiler/moco/import/src/Nodes/Const.cpp
compiler/moco/import/src/Nodes/Conv2D.cpp
compiler/moco/import/src/Nodes/Conv2DBackpropInput.cpp
compiler/moco/import/src/Nodes/DepthwiseConv2dNative.cpp
compiler/moco/import/src/Nodes/FusedBatchNorm.cpp
compiler/moco/import/src/Nodes/MaxPool.cpp
compiler/moco/import/src/Nodes/Mean.cpp
compiler/moco/import/src/Nodes/Placeholder.cpp
compiler/moco/import/src/Nodes/Shape.cpp
compiler/moco/import/src/Nodes/Softmax.cpp
compiler/moco/import/src/Nodes/Squeeze.cpp
compiler/moco/import/src/Nodes/StopGradient.cpp

index 1402c94..c37e6de 100644 (file)
@@ -24,6 +24,7 @@
 #include <loco/IR/PermutingCodec.h>
 #include <stdex/Memory.h>
 #include <plier/tf/Convert.h>
+#include <oops/UserExn.h>
 
 #include <cassert>
 #include <vector>
@@ -67,7 +68,8 @@ namespace moco
 
 bool BiasAddGraphBuilder::validate(const tensorflow::NodeDef &node) const
 {
-  assert(node.input_size() == 2);
+  if (node.input_size() != 2)
+    return false;
 
   // note: even though "data_format" is not entered when a model is written,
   //       TF seems to generate "data_format" field into a pb file
@@ -82,6 +84,12 @@ bool BiasAddGraphBuilder::validate(const tensorflow::NodeDef &node) const
   // but "data_format: A string. 'NHWC' and 'NCHW' are supported."
   // Not sure if value should be 4-D tensor. Let's skip this check for now.
 
+  auto data_layout = plier::tf::get_string_attr(node, "data_format");
+  if (!(data_layout == "NHWC" || data_layout == "NCHW"))
+  {
+    throw oops::UserExn("BiasAdd Unsupported data_format", node.name());
+  }
+
   return true;
 }
 
index 386f9b7..def5a35 100644 (file)
@@ -74,8 +74,6 @@ bool ConcatV2GraphBuilder::validate(const tensorflow::NodeDef &node) const
 
   // Concat node SHOULD have 3 or more inputs, that is 2 + axis
   const int num_inputs = node.input_size() - 1;
-  assert(num_inputs >= 2);
-  assert(num_inputs == plier::tf::get_int_attr(node, "N"));
   return (num_inputs >= 2) && (num_inputs == plier::tf::get_int_attr(node, "N"));
 }
 
index 2e5bc01..8c39d37 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <loco.h>
 #include <plier/tf/Convert.h>
+#include <oops/UserExn.h>
 
 #include <cassert>
 #include <stdexcept>
@@ -61,7 +62,7 @@ void read_value_int32(TFConst *const_node, int num_elements,
   }
   else
   {
-    throw std::runtime_error("Error: Invalid Const values");
+    throw oops::UserExn("Invalid Const values", const_node->name());
   }
 }
 
@@ -95,7 +96,7 @@ void read_value_float32(TFConst *const_node, int num_elements,
   }
   else
   {
-    throw std::runtime_error("Error: Invalid Const values");
+    throw oops::UserExn("Invalid Const values", const_node->name());
   }
 }
 
@@ -106,7 +107,31 @@ namespace moco
 
 bool ConstGraphBuilder::validate(const tensorflow::NodeDef &node) const
 {
-  return plier::tf::has_attrs(node, {"dtype", "value"});
+  if (!plier::tf::has_attrs(node, {"dtype", "value"}))
+    return false;
+
+  const auto &input_tensor = plier::tf::get_tensor_attr(node, "value");
+  const auto &input_shape = input_tensor.tensor_shape();
+  const auto &input_dims = input_shape.dim();
+
+  if (!(input_shape.dim_size() <= 6))
+    return false;
+
+  for (auto &d : input_dims)
+  {
+    if (d.size() > std::numeric_limits<int>::max())
+      throw oops::UserExn("Const Shape element overflows", node.name());
+
+    if (d.size() < 0)
+      throw oops::UserExn("Unknown dim size", node.name());
+  }
+
+  auto dtype = plier::tf::as_loco_datatype(plier::tf::get_datatype_attr(node, "dtype"));
+  if (!(dtype == loco::DataType::S32 || dtype == loco::DataType::FLOAT32))
+    return false;
+  // TODO support other dtype
+
+  return true;
 }
 
 void ConstGraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderContext *context) const
@@ -132,15 +157,12 @@ void ConstGraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderConte
   bool zero_sized_shape = false;
   for (auto &d : input_dims)
   {
-    if (d.size() > std::numeric_limits<int>::max())
-      throw std::runtime_error("Shape element overflows");
+    assert(d.size() <= std::numeric_limits<int>::max());
     if (d.size() == 0)
       zero_sized_shape = true;
 
-    if (d.size() >= 0)
-      const_node->dim(index++) = d.size();
-    else
-      throw std::runtime_error{"Error: Unknown dim size for " + node.name()};
+    assert(d.size() >= 0);
+    const_node->dim(index++) = d.size();
   }
 
   int num_elements = 1;
@@ -170,7 +192,7 @@ void ConstGraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderConte
     // TODO support other types
 
     default:
-      throw std::runtime_error{"Error: Unsupported data type for " + node.name()};
+      assert(false);
   }
 
   // register string-name to node
index 46b55f5..5ccea40 100644 (file)
@@ -26,6 +26,7 @@
 #include <loco/IR/PermutingCodec.h>
 #include <stdex/Memory.h>
 #include <plier/tf/Convert.h>
+#include <oops/UserExn.h>
 
 #include <cassert>
 #include <stdexcept>
@@ -67,20 +68,31 @@ namespace moco
 
 bool Conv2DGraphBuilder::validate(const tensorflow::NodeDef &node) const
 {
-  assert(node.input_size() == 2);
+  if (node.input_size() != 2)
+    return false;
 
   // note: even though "data_format" is not entered when a model is written,
   //       TF seems to generate "data_format" field into a pb file
-  bool has_mandatory_attrs = plier::tf::has_attrs(node, {"T", "data_format", "padding", "strides"});
+  if (!plier::tf::has_attrs(node, {"T", "data_format", "padding", "strides"}))
+    return false;
+
+  auto data_layout = plier::tf::get_string_attr(node, "data_format");
+  if (!(data_layout == "NHWC" || data_layout == "NCHW"))
+  {
+    throw oops::UserExn("Conv2D Unsupported data_format", node.name());
+  }
+
   // dilation attribute is not fully supported
-  bool supported_dilations = true;
   if (plier::tf::has_attr(node, "dilations"))
   {
+    // TODO Support non-default dilations
     auto dilation = plier::tf::get_list_attr(node, "dilations").i();
-    supported_dilations =
-        std::all_of(dilation.begin(), dilation.end(), [](std::int64_t dil) { return dil == 1; });
+    if (!std::all_of(dilation.begin(), dilation.end(), [](std::int64_t dil) { return dil == 1; }))
+      return false;
   }
-  return has_mandatory_attrs && supported_dilations;
+  // Else, dilations are automatically set to default [1,1,1,1] which we assumes now
+
+  return true;
 }
 
 void Conv2DGraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderContext *context) const
@@ -99,10 +111,7 @@ void Conv2DGraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderCont
 
   // read attributes
   auto data_layout = plier::tf::get_string_attr(node, "data_format");
-  if (!(data_layout == "NHWC" || data_layout == "NCHW"))
-  {
-    throw std::runtime_error("Not yet supported");
-  }
+  assert(data_layout == "NHWC" || data_layout == "NCHW");
   conv2d->data_layout(data_layout);
 
   auto tf_strides = plier::tf::get_list_attr(node, "strides");
index df606d6..1fa6e65 100644 (file)
@@ -23,6 +23,7 @@
 #include <loco.h>
 #include <stdex/Memory.h>
 #include <plier/tf/Convert.h>
+#include <oops/UserExn.h>
 
 namespace
 {
@@ -72,28 +73,26 @@ bool Conv2DBackpropInputGraphBuilder::validate(const tensorflow::NodeDef &node)
   if (node.input_size() != 3)
     return false;
 
-  auto check_default_dilations = [](std::vector<int64_t> dilations) -> bool {
-    assert(dilations.size() == 4);
-    for (auto d : dilations)
-    {
-      if (d != 1)
-        return false;
-    }
-    return true;
-  };
+  if (!plier::tf::has_attrs(node, {"T", "data_format", "padding", "strides"}))
+    return false;
 
-  if (plier::tf::has_attr(node, "dilations"))
+  auto data_layout = plier::tf::get_string_attr(node, "data_format");
+  if (!(data_layout == "NHWC" || data_layout == "NCHW"))
   {
-    auto tf_dilations = plier::tf::get_list_attr(node, "dilations");
-    auto dilations = plier::tf::as_int64_list(tf_dilations);
+    throw oops::UserExn("Conv2DBackprop Unsupported data_format", node.name());
+  }
 
+  // dilation attribute is not fully supported
+  if (plier::tf::has_attr(node, "dilations"))
+  {
     // TODO Support non-default dilations
-    if (!check_default_dilations(dilations))
+    auto dilation = plier::tf::get_list_attr(node, "dilations").i();
+    if (!std::all_of(dilation.begin(), dilation.end(), [](std::int64_t dil) { return dil == 1; }))
       return false;
   }
   // Else, dilations are automatically set to default [1,1,1,1] which we assumes now
 
-  return plier::tf::has_attrs(node, {"T", "data_format", "padding", "strides"});
+  return true;
 }
 
 void Conv2DBackpropInputGraphBuilder::build(const tensorflow::NodeDef &node,
@@ -111,8 +110,7 @@ void Conv2DBackpropInputGraphBuilder::build(const tensorflow::NodeDef &node,
 
   // read attributes
   auto data_layout = plier::tf::get_string_attr(node, "data_format");
-  if (!(data_layout == "NHWC" || data_layout == "NCHW"))
-    throw std::runtime_error("Not yet supported");
+  assert(data_layout == "NHWC" || data_layout == "NCHW");
   conv2d_backprop->data_layout(data_layout);
 
   auto tf_strides = plier::tf::get_list_attr(node, "strides");
index e6750d8..be0cfa3 100644 (file)
@@ -25,6 +25,7 @@
 #include <plier/tf/Convert.h>
 #include <loco/IR/PermutingCodec.h>
 #include <stdex/Memory.h>
+#include <oops/UserExn.h>
 
 #include <cassert>
 
@@ -72,11 +73,15 @@ bool DepthwiseConv2dNativeGraphBuilder::validate(const tensorflow::NodeDef &node
   if (node.input_size() != 2)
     return false;
 
-  auto data_layout = get_string_attr(node, "data_format");
+  // note: even though "data_format" and "dilations" are not entered when a model is written,
+  //       TF seems to generate those field into a pb file.
+  if (!has_attrs(node, {"T", "data_format", "dilations", "padding", "strides"}))
+    return false;
+
+  auto data_layout = plier::tf::get_string_attr(node, "data_format");
   if (!(data_layout == "NHWC" || data_layout == "NCHW"))
   {
-    throw std::runtime_error("Not yet supported data layout of DepthwiseConv2dNative: " +
-                             data_layout);
+    throw oops::UserExn("DepthwiseConv2dNative Unsupported data_format", node.name());
   }
 
   auto padding = moco::str_toupper(get_string_attr(node, "padding"));
@@ -87,7 +92,7 @@ bool DepthwiseConv2dNativeGraphBuilder::validate(const tensorflow::NodeDef &node
   auto strides = as_int64_list(tf_strides);
   if (!(strides.size() == 4))
   {
-    throw std::runtime_error("DepthwiseConv2dNative strides requires rank 4");
+    throw oops::UserExn("DepthwiseConv2dNative strides requires rank 4", node.name());
   }
   auto stride_n = strides.at(0);
   auto stride_h = strides.at(1);
@@ -96,12 +101,10 @@ bool DepthwiseConv2dNativeGraphBuilder::validate(const tensorflow::NodeDef &node
   if (!(stride_n == 1 && stride_c == 1) || !(stride_h == stride_w))
   {
     // TODO this message may need to be refined
-    throw std::runtime_error("DepthwiseConv2dNative strides requires N==C==1, H==W");
+    throw oops::UserExn("DepthwiseConv2dNative strides requires N=C=1, H=W", node.name());
   }
 
-  // note: even though "data_format" and "dilations" are not entered when a model is written,
-  //       TF seems to generate those field into a pb file.
-  return has_attrs(node, {"T", "data_format", "dilations", "padding", "strides"});
+  return true;
 }
 
 void DepthwiseConv2dNativeGraphBuilder::build(const tensorflow::NodeDef &node,
index caa72e5..deba237 100644 (file)
@@ -63,7 +63,8 @@ namespace moco
 
 bool FusedBatchNormGraphBuilder::validate(const tensorflow::NodeDef &node) const
 {
-  assert(node.input_size() == 5);
+  if (node.input_size() != 5)
+    return false;
 
   return plier::tf::has_attrs(node, {"epsilon"});
 }
index eab7029..c556c8e 100644 (file)
@@ -26,6 +26,7 @@
 #include <loco/IR/PermutingCodec.h>
 #include <stdex/Memory.h>
 #include <plier/tf/Convert.h>
+#include <oops/UserExn.h>
 
 #include <cassert>
 #include <stdexcept>
@@ -65,7 +66,32 @@ bool MaxPoolGraphBuilder::validate(const tensorflow::NodeDef &node) const
 {
   // note: even though "data_format" is not entered when a model is written,
   //       TF seems to generate "data_format" field into a pb file
-  return plier::tf::has_attrs(node, {"T", "data_format", "ksize", "padding", "strides"});
+  if (!plier::tf::has_attrs(node, {"T", "data_format", "ksize", "padding", "strides"}))
+    return false;
+
+  auto data_layout = plier::tf::get_string_attr(node, "data_format");
+  if (!(data_layout == "NHWC" || data_layout == "NCHW"))
+  {
+    throw oops::UserExn("MaxPool Unsupported data_format", node.name());
+  }
+
+  auto tf_ksize = plier::tf::get_list_attr(node, "ksize");
+  auto ksize = plier::tf::as_int64_list(tf_ksize);
+  if (ksize.size() != 4)
+  {
+    // TODO support ksize length for 1 and 2
+    throw oops::UserExn("MaxPool ksize requires rank 4", node.name());
+  }
+
+  auto tf_strides = plier::tf::get_list_attr(node, "strides");
+  auto strides = plier::tf::as_int64_list(tf_strides);
+  if (strides.size() != 4)
+  {
+    // TODO support strides length for 1 and 2
+    throw oops::UserExn("MaxPool strides requires rank 4", node.name());
+  }
+
+  return true;
 }
 
 void MaxPoolGraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderContext *context) const
@@ -92,21 +118,13 @@ void MaxPoolGraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderCon
   // ksize
   auto tf_ksize = plier::tf::get_list_attr(node, "ksize");
   auto ksize = plier::tf::as_int64_list(tf_ksize);
-  if (ksize.size() != 4)
-  {
-    // TODO support ksize length for 1 and 2
-    throw std::runtime_error("MaxPool only supports ksize length 4");
-  }
+  assert(ksize.size() == 4);
   maxPool_node->ksize(ksize);
 
   // strides
   auto tf_strides = plier::tf::get_list_attr(node, "strides");
   auto strides = plier::tf::as_int64_list(tf_strides);
-  if (strides.size() != 4)
-  {
-    // TODO support strides length for 1 and 2
-    throw std::runtime_error("MaxPool only supports strides length 4");
-  }
+  assert(strides.size() == 4);
   maxPool_node->strides(strides);
 
   // To set the input node of encode_node with node_name
index c9e3a26..cdea9a6 100644 (file)
@@ -65,7 +65,7 @@ bool MeanGraphBuilder::validate(const tensorflow::NodeDef &node) const
   if (node.input_size() != 2)
     return false;
 
-  if (plier::tf::has_attrs(node, {"T", "Tidx", "keep_dims"}) == false)
+  if (!plier::tf::has_attrs(node, {"T", "Tidx", "keep_dims"}))
     return false;
 
   auto dtype = plier::tf::get_datatype_attr(node, "Tidx");
index 77a5be4..d2ab600 100644 (file)
@@ -29,7 +29,15 @@ namespace moco
 
 bool PlaceholderGraphBuilder::validate(const tensorflow::NodeDef &node) const
 {
-  return plier::tf::has_attrs(node, {"dtype", "shape"});
+  if (!plier::tf::has_attrs(node, {"dtype", "shape"}))
+    return false;
+
+  loco::DataType dtype = plier::tf::as_loco_datatype(plier::tf::get_datatype_attr(node, "dtype"));
+  if (dtype != loco::DataType::FLOAT32)
+    return false;
+  // TODO support other types
+
+  return true;
 }
 
 void PlaceholderGraphBuilder::build(const tensorflow::NodeDef &node,
index d295bcd..d45374b 100644 (file)
@@ -58,7 +58,8 @@ namespace moco
 
 bool ShapeGraphBuilder::validate(const tensorflow::NodeDef &node) const
 {
-  assert(node.input_size() == 1);
+  if (node.input_size() != 1)
+    return false;
 
   return plier::tf::has_attrs(node, {"T"});
 }
index fa04797..1c92968 100644 (file)
@@ -58,7 +58,8 @@ namespace moco
 
 bool SoftmaxGraphBuilder::validate(const tensorflow::NodeDef &node) const
 {
-  assert(node.input_size() == 1);
+  if (node.input_size() != 1)
+    return false;
 
   return plier::tf::has_attrs(node, {"T"});
 }
index 249673f..0e84cec 100644 (file)
@@ -23,6 +23,7 @@
 #include <loco.h>
 #include <stdex/Memory.h>
 #include <plier/tf/Convert.h>
+#include <oops/UserExn.h>
 
 namespace
 {
@@ -60,9 +61,19 @@ namespace moco
 
 bool SqueezeGraphBuilder::validate(const tensorflow::NodeDef &node) const
 {
-  assert(node.input_size() == 1);
+  if (node.input_size() != 1)
+    return false;
 
-  return plier::tf::has_attrs(node, {"T"});
+  if (!plier::tf::has_attrs(node, {"T"}))
+    return false;
+
+  if (plier::tf::has_attrs(node, {"axis"}))
+  {
+    // TODO support 'axis' attribute
+    oops::UserExn("Squeeze: Unsupported 'axis' attribute", node.name());
+  }
+
+  return true;
 }
 
 void SqueezeGraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderContext *context) const
@@ -73,11 +84,8 @@ void SqueezeGraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderCon
   SymbolTable *tensor_names = context->tensor_names();
   UpdateQueue *updates = context->updates();
 
-  if (plier::tf::has_attrs(node, {"axis"}))
-  {
-    // TODO support 'axis' attribute
-    std::runtime_error("Import Squeeze: 'axis' attribute is not supported yet");
-  }
+  // TODO support 'axis' attribute
+  assert(!plier::tf::has_attrs(node, {"axis"}));
 
   std::vector<int64_t> squeeze_dims;
   if (plier::tf::has_attrs(node, {"squeeze_dims"}))
index fafdfa4..49ec17c 100644 (file)
@@ -55,7 +55,8 @@ namespace moco
 
 bool StopGradientGraphBuilder::validate(const tensorflow::NodeDef &node) const
 {
-  assert(node.input_size() == 1);
+  if (node.input_size() != 1)
+    return false;
 
   return plier::tf::has_attrs(node, {"T"});
 }