[onert] Fix conv2d op for dilation (#3932)
authorYiHyunJin <33678155+YiHyunJin@users.noreply.github.com>
Mon, 24 Aug 2020 06:04:33 +0000 (15:04 +0900)
committerGitHub <noreply@github.com>
Mon, 24 Aug 2020 06:04:33 +0000 (15:04 +0900)
When using MultiThread, both dilation data must be 1.
When obtaining padding data, dilation data is used.
Move additional conditions of dilation into usableMultiThreaded

Signed-off-by: YiHyunjin <hj0412.yi@samsung.com>
compute/cker/include/cker/operation/Conv.h
runtime/onert/backend/cpu/KernelGenerator.cc
runtime/onert/backend/cpu/ops/ConvolutionLayer.cc
runtime/onert/core/include/ir/Padding.h
runtime/onert/core/src/ir/Padding.cc
runtime/onert/core/src/util/ShapeInference.cc

index 1bf191b..f28004d 100644 (file)
@@ -61,11 +61,12 @@ public:
   }
 
   void prepare(const Shape &filter_shape, const float *filter_data, PaddingType padding_type,
-               bool &is_replaced_weights)
+               bool &is_replaced_weights, uint32_t dilationWidthFactor,
+               uint32_t dilationHeightFactor)
   {
     if (!_prepared)
     {
-      if (usableMultiThreaded(padding_type))
+      if (usableMultiThreaded(padding_type, dilationWidthFactor, dilationHeightFactor))
       {
         transposeFilter(filter_shape, filter_data, is_replaced_weights);
       }
@@ -87,7 +88,8 @@ public:
                   const Shape &filter_shape, const float *filter_data, const Shape &bias_shape,
                   const float *bias_data, const Shape &output_shape, float *output_data)
   {
-    if (usableMultiThreaded(params.padding_type))
+    if (usableMultiThreaded(params.padding_type, params.dilation_width_factor,
+                            params.dilation_height_factor))
     {
       bool transposed_in_execution = false;
       if (!_prepared)
@@ -125,9 +127,11 @@ public:
   }
 
 private:
-  bool usableMultiThreaded(PaddingType padding_type)
+  bool usableMultiThreaded(PaddingType padding_type, uint32_t dilation_width_factor,
+                           int32_t dilation_height_factor)
   {
-    return padding_type != PaddingType::kNone && std::thread::hardware_concurrency() > 1;
+    return padding_type != PaddingType::kNone && std::thread::hardware_concurrency() > 1 &&
+           dilation_width_factor == 1 && dilation_height_factor == 1;
   }
 
   void transposeFilter(const Shape &filter_shape, const float *filter_data,
index 134d46c..7d57996 100644 (file)
@@ -278,7 +278,8 @@ void KernelGenerator::visit(const ir::operation::Conv2D &node)
   const auto ker_width = ker_shape.dim(2);
 
   const auto padding =
-      ir::calculatePadding(param_padding, ifm_shape, ofm_shape, stride, ker_width, ker_height);
+      ir::calculatePadding(param_padding, ifm_shape, ofm_shape, stride, ker_width, ker_height,
+                           dilation.width_factor, dilation.height_factor);
 
   fn->configure(ifm_tensor, ker_tensor, bias_tensor, param_padding.type, padding.left,
                 padding.right, padding.top, padding.bottom, stride.horizontal, stride.vertical,
index 664cd34..c057267 100644 (file)
@@ -150,7 +150,8 @@ void ConvolutionLayer::run()
     param_padding.param.bottom = _paddingBottom;
 
     const auto padding =
-        ir::calculatePadding(param_padding, ifm_shape, ofm_shape, stride, ker_width, ker_height);
+        ir::calculatePadding(param_padding, ifm_shape, ofm_shape, stride, ker_width, ker_height,
+                             _dilationWidthFactor, _dilationHeightFactor);
 
     _paddingLeft = padding.left;
     _paddingRight = padding.right;
@@ -181,7 +182,8 @@ void ConvolutionLayer::prepare()
   {
     bool is_transposed = false;
     kernel.prepare(getTensorShape(_kernel), reinterpret_cast<const float *>(_kernel->buffer()),
-                   getPaddingType(_paddingType), is_transposed);
+                   getPaddingType(_paddingType), is_transposed, _dilationWidthFactor,
+                   _dilationHeightFactor);
 
     // Decrease reference of _kernel(weights) only when _kernel is constant
     if (is_transposed)
index b905391..8a7bcdb 100644 (file)
@@ -65,7 +65,8 @@ struct Padding
 // TODO Change to Padding struct's method
 const ExplicitPadding calculatePadding(const Padding &padding, const FeatureShape &ifm_shape,
                                        const FeatureShape &ofm_shape, const Stride &stride,
-                                       uint32_t kw, uint32_t kh);
+                                       uint32_t kw, uint32_t kh, uint32_t dwf = 1,
+                                       uint32_t dhf = 1);
 
 } // namespace ir
 } // namespace onert
index 3196991..d74f802 100644 (file)
@@ -50,7 +50,7 @@ inline ExplicitPadding validPadding(void)
 }
 
 inline ExplicitPadding samePaddingUsingIFM(const FeatureShape &ifm_shape, const Stride &stride,
-                                           uint32_t kw, uint32_t kh)
+                                           uint32_t kw, uint32_t kh, uint32_t dwf, uint32_t dhf)
 {
   ExplicitPadding padding;
 
@@ -61,14 +61,19 @@ inline ExplicitPadding samePaddingUsingIFM(const FeatureShape &ifm_shape, const
   // padding_to_beginning = total_padding / 2
   // padding_to_end = (total_padding + 1)/2.
   //
+  const int32_t effective_filter_h_size = (kh - 1) * dhf + 1;
+  const int32_t effective_filter_w_size = (kw - 1) * dwf + 1;
+
   const int32_t vertical_expected_output = (ifm_shape.H + stride.vertical - 1) / stride.vertical;
   const int32_t horizontal_expected_output =
       (ifm_shape.W + stride.horizontal - 1) / stride.horizontal;
 
-  const int32_t vertical_needed_input = (vertical_expected_output - 1) * stride.vertical + kh;
+  const int32_t vertical_needed_input =
+      (vertical_expected_output - 1) * stride.vertical + effective_filter_h_size;
   const int32_t vertical_total_padding = std::max(0, vertical_needed_input - ifm_shape.H);
 
-  const int32_t horizontal_needed_input = (horizontal_expected_output - 1) * stride.horizontal + kw;
+  const int32_t horizontal_needed_input =
+      (horizontal_expected_output - 1) * stride.horizontal + effective_filter_w_size;
   const int32_t horizontal_total_padding = std::max(0, horizontal_needed_input - ifm_shape.W);
 
   padding.top = vertical_total_padding / 2;
@@ -80,7 +85,8 @@ inline ExplicitPadding samePaddingUsingIFM(const FeatureShape &ifm_shape, const
 }
 
 inline ExplicitPadding samePadding(const FeatureShape &ifm_shape, const FeatureShape &ofm_shape,
-                                   const Stride &stride, uint32_t kw, uint32_t kh)
+                                   const Stride &stride, uint32_t kw, uint32_t kh, uint32_t dwf,
+                                   uint32_t dhf)
 {
   const int32_t vertical_expected_output = (ifm_shape.H + stride.vertical - 1) / stride.vertical;
   const int32_t horizontal_expected_output =
@@ -92,7 +98,7 @@ inline ExplicitPadding samePadding(const FeatureShape &ifm_shape, const FeatureS
   UNUSED_RELEASE(vertical_expected_output);
   UNUSED_RELEASE(horizontal_expected_output);
 
-  return samePaddingUsingIFM(ifm_shape, stride, kw, kh);
+  return samePaddingUsingIFM(ifm_shape, stride, kw, kh, dwf, dhf);
 }
 
 } // namespace
@@ -130,7 +136,7 @@ Padding::Padding(uint32_t left, uint32_t right, uint32_t top, uint32_t bottom)
 
 const ExplicitPadding calculatePadding(const Padding &padding, const FeatureShape &ifm_shape,
                                        const FeatureShape &ofm_shape, const Stride &stride,
-                                       uint32_t kw, uint32_t kh)
+                                       uint32_t kw, uint32_t kh, uint32_t dwf, uint32_t dhf)
 {
   if (padding.type == PaddingType::EXPLICIT)
   {
@@ -138,7 +144,7 @@ const ExplicitPadding calculatePadding(const Padding &padding, const FeatureShap
   }
   else if (padding.type == PaddingType::SAME)
   {
-    return samePadding(ifm_shape, ofm_shape, stride, kw, kh);
+    return samePadding(ifm_shape, ofm_shape, stride, kw, kh, dwf, dhf);
   }
   else if (padding.type == PaddingType::VALID)
   {
index 13ade7d..95c1504 100644 (file)
@@ -79,34 +79,8 @@ ir::Shape broadcastShapes(const ir::Shape &lhs_shape, const ir::Shape &rhs_shape
 // Calculate output height and width of convolution-like operation
 std::pair<int, int> calcConvLikeHeightAndWidth(const int in_h, const int in_w, const int ker_h,
                                                const int ker_w, const ir::Padding pad,
-                                               const ir::Stride stride)
-{
-  int32_t out_h = 0, out_w = 0;
-
-  switch (pad.type)
-  {
-    case ir::PaddingType::SAME:
-      out_h = ceil_div(in_h, stride.vertical);
-      out_w = ceil_div(in_w, stride.horizontal);
-      break;
-    case ir::PaddingType::VALID:
-      out_h = ceil_div(in_h - ker_h + 1, stride.vertical);
-      out_w = ceil_div(in_w - ker_w + 1, stride.horizontal);
-      break;
-    case ir::PaddingType::EXPLICIT:
-      out_h = (in_h + pad.param.top + pad.param.bottom - ker_h) / stride.vertical + 1;
-      out_w = (in_w + pad.param.left + pad.param.right - ker_w) / stride.horizontal + 1;
-      break;
-    default:
-      assert(false);
-  }
-
-  return {out_h, out_w};
-}
-
-std::pair<int, int> calcConvLikeHeightAndWidth(const int in_h, const int in_w, const int ker_h,
-                                               const int ker_w, const ir::Padding pad,
-                                               const ir::Stride stride, const ir::Dilation dilation)
+                                               const ir::Stride stride,
+                                               const ir::Dilation dilation = {1, 1})
 {
   int32_t out_h = 0, out_w = 0;
   int32_t effective_filter_w_size = (ker_w - 1) * dilation.width_factor + 1;