[mir-caffe2-importer] Perform operation sanity checks while creating (#6037)
authorIvan Vagin/AI Tools Lab /SRR/Engineer/삼성전자 <ivan.vagin@samsung.com>
Thu, 1 Aug 2019 10:47:42 +0000 (13:47 +0300)
committerEfimov Alexander/AI Tools Lab/./Samsung Electronics <a.efimov@samsung.com>
Thu, 1 Aug 2019 10:47:42 +0000 (13:47 +0300)
Perform operation sanity checks while creating it

Signed-off-by: Ivan Vagin <ivan.vagin@samsung.com>
compiler/mir-caffe2-importer/caffe2_importer.cpp
compiler/mir-caffe2-importer/caffe2_importer.h
compiler/mir-caffe2-importer/caffe2_op_creator.cpp
compiler/mir-caffe2-importer/caffe2_op_creator.h

index e8ea29a..7d6bd71 100644 (file)
@@ -109,59 +109,19 @@ std::unique_ptr<mir::Graph> Caffe2Importer::importModel()
 
 void Caffe2Importer::collectUnsupportedOps()
 {
+  std::set<std::string> unsupportedOps;
   for (auto &op : _net->op())
-    collectUnsupportedOp(op);
-
-  if (!_problemsOpSet.empty())
   {
-    std::string msg("NNC can't load model. Detected problems:");
-    for (const auto &problemStr : _problemsOpSet)
-      msg.append("\n  * " + problemStr);
-    throw std::runtime_error(msg);
+    if (_operatorTypes.find(op.type()) == _operatorTypes.end())
+      unsupportedOps.insert(op.type());
   }
-}
 
-void Caffe2Importer::collectUnsupportedOp(const OperatorDef &op)
-{
-  if (_operatorTypes.find(op.type()) == _operatorTypes.end())
+  if (!unsupportedOps.empty())
   {
-    _problemsOpSet.insert(op.type() + ": unknown layer");
-    return;
-  }
-
-  SupportedCaffe2OpType opType = _operatorTypes.at(op.type());
-  switch (opType)
-  {
-    case SupportedCaffe2OpType::FC:
-      _opCreator->checkFC(op, _problemsOpSet);
-      break;
-    case SupportedCaffe2OpType::spatialBN:
-      _opCreator->checkSpatialBN(op, _problemsOpSet);
-      break;
-    case SupportedCaffe2OpType::averagePool:
-    case SupportedCaffe2OpType::conv:
-    case SupportedCaffe2OpType::maxPool:
-      _opCreator->checkConvLikeOp(op, _problemsOpSet);
-      break;
-    case SupportedCaffe2OpType::add:
-    case SupportedCaffe2OpType::concat:
-    case SupportedCaffe2OpType::constantFill:
-    case SupportedCaffe2OpType::dropout:
-    case SupportedCaffe2OpType::givenTensorFill:
-    case SupportedCaffe2OpType::givenTensorInt64Fill:
-    case SupportedCaffe2OpType::mul:
-    case SupportedCaffe2OpType::relu:
-    case SupportedCaffe2OpType::resizeNearest:
-    case SupportedCaffe2OpType::sigmoid:
-    case SupportedCaffe2OpType::softmax:
-    case SupportedCaffe2OpType::sum:
-    case SupportedCaffe2OpType::clip:
-    case SupportedCaffe2OpType::reshape:
-      _opCreator->commonCheck(op, _problemsOpSet);
-      break;
-    default:
-      _problemsOpSet.insert(op.type() + ": unsupported layer");
-      break;
+    std::string exceptionMsg("Can't load model, unsupported operators:");
+    for (const auto &op : unsupportedOps)
+      exceptionMsg.append("\n  * " + op);
+    throw std::runtime_error(exceptionMsg);
   }
 }
 
index 1b39341..5da1199 100644 (file)
@@ -48,8 +48,6 @@ private:
   std::vector<mir::Shape> _inputShapes;
 
   static const std::map<std::string, SupportedCaffe2OpType> _operatorTypes;
-  // set of strings describing incorrect parts of network and parts of network unsupported by NNC
-  std::set<std::string> _problemsOpSet;
 
   // Maps Caffe2 operator input names to corresponding MIR operation outputs.
   std::unordered_map<std::string, mir::Operation::Output *> _blobNameToOutput;
@@ -67,11 +65,6 @@ private:
   void collectUnsupportedOps();
 
   /**
-   * @brief Collecting unsupported parts of caffe2 operator
-   */
-  void collectUnsupportedOp(const ::caffe2::OperatorDef &op);
-
-  /**
    * @brief Creating MIR node from single caffe2 operator
    */
   void createMIRNodesFromOp(const ::caffe2::OperatorDef &op);
index 0d23a62..684f867 100644 (file)
@@ -238,64 +238,41 @@ mir::Operation::Output *Caffe2OpCreator::convertMIRToCaffe(mir::Operation::Outpu
 // Check functions
 //
 
-void Caffe2OpCreator::checkConvLikeOp(const ::caffe2::OperatorDef &op,
-                                      std::set<std::string> &problems_ops_set)
+static void checkLayout(const OperatorDef &op)
 {
-  commonCheck(op, problems_ops_set);
+  if (getSingleArgument(op, "order", "NCHW") != "NCHW")
+    throw std::runtime_error(op.type() + ": only 'NCHW' axis order is supported");
+}
+
+static void checkConvLikeOp(const ::caffe2::OperatorDef &op)
+{
+  checkLayout(op);
 
   // Padding
   bool has_custom_pad = hasArgument(op.arg(), "pad_l") || hasArgument(op.arg(), "pad_r") ||
                         hasArgument(op.arg(), "pad_t") || hasArgument(op.arg(), "pad_b");
 
   if (has_custom_pad && hasArgument(op.arg(), "pad"))
-    problems_ops_set.insert("Custom pad can't be combined with overall pad");
+    throw std::runtime_error("Custom pad can't be combined with overall pad");
 
   if (has_custom_pad &&
       !(hasArgument(op.arg(), "pad_l") && hasArgument(op.arg(), "pad_r") &&
         hasArgument(op.arg(), "pad_t") && hasArgument(op.arg(), "pad_b")))
-    problems_ops_set.insert("If one custom pad specified - all custom pads must be specified");
+    throw std::runtime_error("If one custom pad specified - all custom pads must be specified");
 
   // Kernel size
   bool has_custom_kernel_size =
       hasArgument(op.arg(), "kernel_h") || hasArgument(op.arg(), "kernel_w");
 
   if (has_custom_kernel_size && hasArgument(op.arg(), "kernel"))
-    problems_ops_set.insert("Custom kernel size can't be combined with overall kernel size");
+    throw std::runtime_error("Custom kernel size can't be combined with overall kernel size");
 
   if (has_custom_kernel_size &&
       !(hasArgument(op.arg(), "kernel_h") && hasArgument(op.arg(), "kernel_w")))
-    problems_ops_set.insert(
+    throw std::runtime_error(
         "If one custom kernel size specified - all custom kernel sizes must be specified");
 }
 
-void Caffe2OpCreator::checkFC(const ::caffe2::OperatorDef &op,
-                              std::set<std::string> &problems_ops_set)
-{
-  commonCheck(op, problems_ops_set);
-  for (auto &s : {"axis", "axis_w", "float16_compute"})
-    if (hasArgument(op.arg(), s))
-      problems_ops_set.insert(std::string("FC: only default '") + s + "' value is supported");
-}
-
-void Caffe2OpCreator::checkSpatialBN(const ::caffe2::OperatorDef &op,
-                                     std::set<std::string> &problems_ops_set)
-{
-  commonCheck(op, problems_ops_set);
-  if (op.input_size() != 5)
-    problems_ops_set.insert(
-        "SpatialBN must have exactly 5 inputs ('sums' and 'sumsq' are not supported yet)");
-
-  if (getSingleArgument(op, "is_test", 1) != 1)
-    problems_ops_set.insert(std::string("SpatialBN: only test mode supported"));
-}
-
-void Caffe2OpCreator::commonCheck(const ::caffe2::OperatorDef &op,
-                                  std::set<std::string> &problems_ops_set)
-{
-  if (getSingleArgument(op, "order", "NCHW") != "NCHW")
-    problems_ops_set.insert("Only 'NCHW' axis order is supported");
-}
-
 //
 // Convert functions
 //
@@ -304,6 +281,7 @@ std::vector<mir::Operation::Output *>
 Caffe2OpCreator::convertAdd(const std::vector<mir::Operation::Output *> &inputs,
                             const ::caffe2::OperatorDef &op, const MIRTensors &mir_tensors)
 {
+  checkLayout(op);
 
   std::vector<mir::Operation::Output *> add_input;
   add_input.reserve(inputs.size() + 1);
@@ -327,6 +305,8 @@ std::vector<mir::Operation::Output *>
 Caffe2OpCreator::convertAveragePool(const std::vector<mir::Operation::Output *> &inputs,
                                     const OperatorDef &op)
 {
+  checkConvLikeOp(op);
+
   Shape window_shape = getWindowShape(op, inputs);
 
   Shape strides(getStrides(op));
@@ -347,6 +327,8 @@ std::vector<mir::Operation::Output *>
 Caffe2OpCreator::convertConv(const std::vector<mir::Operation::Output *> &inputs,
                              const ::caffe2::OperatorDef &op, const MIRTensors &mir_tensors)
 {
+  checkConvLikeOp(op);
+
   // dilation order: h w (not used)
   Shape stride_shape(getStrides(op));
 
@@ -392,6 +374,8 @@ std::vector<mir::Operation::Output *>
 Caffe2OpCreator::convertConcat(const std::vector<mir::Operation::Output *> &inputs,
                                const ::caffe2::OperatorDef &op)
 {
+  checkLayout(op);
+
   int axis = getSingleArgument(op, "axis", 1);
   auto result = createOp<ops::ConcatOp>("Concat", inputs, axis);
   return {result->getOutput(0)};
@@ -415,6 +399,10 @@ Caffe2OpCreator::convertFullyConnected(const std::vector<mir::Operation::Output
                                        const ::caffe2::OperatorDef &op,
                                        const MIRTensors &mir_tensors)
 {
+  for (auto &s : {"axis", "axis_w", "float16_compute"})
+    if (hasArgument(op.arg(), s))
+      throw std::runtime_error(std::string("FC: only default '") + s + "' value is supported");
+
   auto weights_tensor = transposeTensor<1, 0>(mir_tensors.at(op.input(1)));
 
   const auto &input_shape = inputs[0]->getShape();
@@ -434,6 +422,8 @@ std::vector<mir::Operation::Output *>
 Caffe2OpCreator::convertMaxPool(const std::vector<mir::Operation::Output *> &inputs,
                                 const OperatorDef &op)
 {
+  checkConvLikeOp(op);
+
   Shape window_shape = getWindowShape(op, inputs);
   Shape strides(getStrides(op));
 
@@ -453,6 +443,7 @@ std::vector<mir::Operation::Output *>
 Caffe2OpCreator::convertMul(const std::vector<mir::Operation::Output *> &inputs,
                             const ::caffe2::OperatorDef &op, const MIRTensors &mir_tensors)
 {
+  checkLayout(op);
 
   std::vector<mir::Operation::Output *> input_descriptors;
   input_descriptors.reserve(inputs.size() + 1);
@@ -516,6 +507,15 @@ std::vector<mir::Operation::Output *>
 Caffe2OpCreator::convertSpatialBN(const std::vector<mir::Operation::Output *> &inputs,
                                   const ::caffe2::OperatorDef &op, const MIRTensors &mir_tensors)
 {
+  checkLayout(op);
+
+  // Sanity checks
+  if (op.input_size() != 5)
+    throw std::runtime_error(
+        "SpatialBN must have exactly 5 inputs ('sums' and 'sumsq' are not supported yet)");
+  if (getSingleArgument(op, "is_test", 1) != 1)
+    throw std::runtime_error("SpatialBN: only test mode supported");
+
   // overall_res = (X - mean) / sqrt(var + epsilon) * scale + bias
 
   const auto &scale_tensor = mir_tensors.at(op.input(1));
index 63a2d67..f8e50d4 100644 (file)
@@ -43,14 +43,6 @@ class Caffe2OpCreator
 public:
   explicit Caffe2OpCreator(Graph *g) : _graph(g){};
 
-  void checkConvLikeOp(const ::caffe2::OperatorDef &op, std::set<std::string> &problems_ops_set);
-
-  void checkFC(const ::caffe2::OperatorDef &op, std::set<std::string> &problems_ops_set);
-
-  void checkSpatialBN(const ::caffe2::OperatorDef &op, std::set<std::string> &problems_ops_set);
-
-  void commonCheck(const ::caffe2::OperatorDef &op, std::set<std::string> &problems_ops_set);
-
   std::vector<mir::Operation::Output *> createInput(const std::string &name,
                                                     const mir::Shape &shape);