From dc41641517c6443dccd5a53b1b9b094449bf1794 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ivan=20Vagin/AI=20Tools=20Lab=20/SRR/Engineer/=EC=82=BC?= =?utf8?q?=EC=84=B1=EC=A0=84=EC=9E=90?= Date: Thu, 1 Aug 2019 13:47:42 +0300 Subject: [PATCH] [mir-caffe2-importer] Perform operation sanity checks while creating (#6037) Perform operation sanity checks while creating it Signed-off-by: Ivan Vagin --- compiler/mir-caffe2-importer/caffe2_importer.cpp | 56 +++-------------- compiler/mir-caffe2-importer/caffe2_importer.h | 7 --- compiler/mir-caffe2-importer/caffe2_op_creator.cpp | 70 +++++++++++----------- compiler/mir-caffe2-importer/caffe2_op_creator.h | 8 --- 4 files changed, 43 insertions(+), 98 deletions(-) diff --git a/compiler/mir-caffe2-importer/caffe2_importer.cpp b/compiler/mir-caffe2-importer/caffe2_importer.cpp index e8ea29a..7d6bd71 100644 --- a/compiler/mir-caffe2-importer/caffe2_importer.cpp +++ b/compiler/mir-caffe2-importer/caffe2_importer.cpp @@ -109,59 +109,19 @@ std::unique_ptr Caffe2Importer::importModel() void Caffe2Importer::collectUnsupportedOps() { + std::set 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); } } diff --git a/compiler/mir-caffe2-importer/caffe2_importer.h b/compiler/mir-caffe2-importer/caffe2_importer.h index 1b39341..5da1199 100644 --- a/compiler/mir-caffe2-importer/caffe2_importer.h +++ b/compiler/mir-caffe2-importer/caffe2_importer.h @@ -48,8 +48,6 @@ private: std::vector _inputShapes; static const std::map _operatorTypes; - // set of strings describing incorrect parts of network and parts of network unsupported by NNC - std::set _problemsOpSet; // Maps Caffe2 operator input names to corresponding MIR operation outputs. std::unordered_map _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); diff --git a/compiler/mir-caffe2-importer/caffe2_op_creator.cpp b/compiler/mir-caffe2-importer/caffe2_op_creator.cpp index 0d23a62..684f867 100644 --- a/compiler/mir-caffe2-importer/caffe2_op_creator.cpp +++ b/compiler/mir-caffe2-importer/caffe2_op_creator.cpp @@ -238,64 +238,41 @@ mir::Operation::Output *Caffe2OpCreator::convertMIRToCaffe(mir::Operation::Outpu // Check functions // -void Caffe2OpCreator::checkConvLikeOp(const ::caffe2::OperatorDef &op, - std::set &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 &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 &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 &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 Caffe2OpCreator::convertAdd(const std::vector &inputs, const ::caffe2::OperatorDef &op, const MIRTensors &mir_tensors) { + checkLayout(op); std::vector add_input; add_input.reserve(inputs.size() + 1); @@ -327,6 +305,8 @@ std::vector Caffe2OpCreator::convertAveragePool(const std::vector &inputs, const OperatorDef &op) { + checkConvLikeOp(op); + Shape window_shape = getWindowShape(op, inputs); Shape strides(getStrides(op)); @@ -347,6 +327,8 @@ std::vector Caffe2OpCreator::convertConv(const std::vector &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 Caffe2OpCreator::convertConcat(const std::vector &inputs, const ::caffe2::OperatorDef &op) { + checkLayout(op); + int axis = getSingleArgument(op, "axis", 1); auto result = createOp("Concat", inputs, axis); return {result->getOutput(0)}; @@ -415,6 +399,10 @@ Caffe2OpCreator::convertFullyConnected(const std::vector(mir_tensors.at(op.input(1))); const auto &input_shape = inputs[0]->getShape(); @@ -434,6 +422,8 @@ std::vector Caffe2OpCreator::convertMaxPool(const std::vector &inputs, const OperatorDef &op) { + checkConvLikeOp(op); + Shape window_shape = getWindowShape(op, inputs); Shape strides(getStrides(op)); @@ -453,6 +443,7 @@ std::vector Caffe2OpCreator::convertMul(const std::vector &inputs, const ::caffe2::OperatorDef &op, const MIRTensors &mir_tensors) { + checkLayout(op); std::vector input_descriptors; input_descriptors.reserve(inputs.size() + 1); @@ -516,6 +507,15 @@ std::vector Caffe2OpCreator::convertSpatialBN(const std::vector &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)); diff --git a/compiler/mir-caffe2-importer/caffe2_op_creator.h b/compiler/mir-caffe2-importer/caffe2_op_creator.h index 63a2d67..f8e50d4 100644 --- a/compiler/mir-caffe2-importer/caffe2_op_creator.h +++ b/compiler/mir-caffe2-importer/caffe2_op_creator.h @@ -43,14 +43,6 @@ class Caffe2OpCreator public: explicit Caffe2OpCreator(Graph *g) : _graph(g){}; - void checkConvLikeOp(const ::caffe2::OperatorDef &op, std::set &problems_ops_set); - - void checkFC(const ::caffe2::OperatorDef &op, std::set &problems_ops_set); - - void checkSpatialBN(const ::caffe2::OperatorDef &op, std::set &problems_ops_set); - - void commonCheck(const ::caffe2::OperatorDef &op, std::set &problems_ops_set); - std::vector createInput(const std::string &name, const mir::Shape &shape); -- 2.7.4