From: Ivan Vagin/AI Tools Lab /SRR/Engineer/삼성전자 Date: Mon, 21 Jan 2019 15:47:55 +0000 (+0300) Subject: [nnc] Fixed several ACL bugs (#2900) X-Git-Tag: nncc_backup~937 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=afb71e0d82f8c58c2eb1b6271b824c0be4244fcc;p=platform%2Fcore%2Fml%2Fnnfw.git [nnc] Fixed several ACL bugs (#2900) * Increased padding if caffe formula for pooling output producing wrong result * Removed `RoundMode` from `PoolOp` * Added missing argument for generated `CLArithmeticAddition` call Signed-off-by: Ivan Vagin --- diff --git a/contrib/nnc/core/modelIR/operations/PoolOp.cpp b/contrib/nnc/core/modelIR/operations/PoolOp.cpp index 318dd47..29f5638 100644 --- a/contrib/nnc/core/modelIR/operations/PoolOp.cpp +++ b/contrib/nnc/core/modelIR/operations/PoolOp.cpp @@ -35,30 +35,12 @@ void PoolOp::inferOutputShapes() { output_shape.dim(0) = input_shape.dim(0); output_shape.dim(3) = input_shape.dim(3); - // Height and width. - switch (_roundMode) { - case RoundMode::ceil: - for (int i = 0; i < 2; i++) { - auto padded_input = input_shape.dim(1 + i) + _paddingBefore.at(i) + _paddingAfter.at(i); - // Incorrect formula taken from Caffe leading to out-of-bound accesses. - // out_size = ceil((in_size - window_size) / stride) + 1 = - // = (in_size - window_size + stride - 1) / stride + 1 = - // = ceil((in_size - window_size + stride) / stride) - output_shape.dim(1 + i) = - (padded_input - _windowShape.dim(i) + _strides.dim(i) - 1) / _strides.dim(i) + 1; - } - break; - case RoundMode::floor: - for (int i = 0; i < 2; i++) { - auto padded_input = input_shape.dim(1 + i) + _paddingBefore.at(i) + _paddingAfter.at(i); - // out_size = ceil((in_size - window_size + 1) / stride) = - // (in_size - window_size + 1 + stride - 1) / stride = - // (in_size - window_size) / stride + 1 - output_shape.dim(1 + i) = (padded_input - _windowShape.dim(i)) / _strides.dim(i) + 1; - } - break; - default: - assert(false); + for (int i = 0; i < 2; i++) { + auto padded_input = input_shape.dim(1 + i) + _paddingBefore.at(i) + _paddingAfter.at(i); + // out_size = ceil((in_size - window_size + 1) / stride) = + // (in_size - window_size + 1 + stride - 1) / stride = + // (in_size - window_size) / stride + 1 + output_shape.dim(1 + i) = (padded_input - _windowShape.dim(i)) / _strides.dim(i) + 1; } for (int i = 0; i < output_shape.rank(); i++) { diff --git a/contrib/nnc/include/core/modelIR/operations/PoolOp.h b/contrib/nnc/include/core/modelIR/operations/PoolOp.h index 19e9f32..37ff694 100644 --- a/contrib/nnc/include/core/modelIR/operations/PoolOp.h +++ b/contrib/nnc/include/core/modelIR/operations/PoolOp.h @@ -39,28 +39,20 @@ public: EMPTY // Consider that there are no elements outside of input shape }; - // Rounding mode to use when calculating the output size. - enum class RoundMode { - ceil, - floor - }; - PoolOp(const IODescriptor& arg, PoolingType pooling_type, const Shape& window_shape, const Shape& strides, const std::vector& padding_before, const std::vector& padding_after, - BorderType border_type, - RoundMode round_mode) + BorderType border_type) : Operation(Type::pool, {arg}), _poolingType(pooling_type), _windowShape(window_shape), _strides(strides), _paddingBefore(padding_before), _paddingAfter(padding_after), - _borderType(border_type), - _roundMode(round_mode) { + _borderType(border_type) { inferOutputShapes(); } @@ -85,7 +77,6 @@ private: std::vector _paddingBefore; std::vector _paddingAfter; BorderType _borderType; - RoundMode _roundMode; }; } // namespace ops diff --git a/contrib/nnc/passes/acl_soft_backend/AclCppOpGenerator.cpp b/contrib/nnc/passes/acl_soft_backend/AclCppOpGenerator.cpp index 2df49b1..8f69740 100644 --- a/contrib/nnc/passes/acl_soft_backend/AclCppOpGenerator.cpp +++ b/contrib/nnc/passes/acl_soft_backend/AclCppOpGenerator.cpp @@ -801,7 +801,9 @@ shared_ptr AclCppOpGenerator::genAddition(const string& prefix, int auto arithmetic_add_layer = arithmetic_add_layer_var->use(); // Generate the call: arithmetic_add_layer.configure(&in1, &in2, &out); - _constrBlock->call("configure", {AF::ref(in1), AF::ref(in2), AF::ref(out)}, arithmetic_add_layer); + _constrBlock->call("configure", {AF::ref(in1), AF::ref(in2), AF::ref(out), + AF::lit("arm_compute::ConvertPolicy::WRAP")}, + arithmetic_add_layer); // Generate the call: arithmetic_add_layer.run(); _infBlock->call("run", {}, arithmetic_add_layer); diff --git a/contrib/nnc/passes/caffe2_frontend/caffe2_op_creator.cpp b/contrib/nnc/passes/caffe2_frontend/caffe2_op_creator.cpp index 4f7c46a..d9bd917 100644 --- a/contrib/nnc/passes/caffe2_frontend/caffe2_op_creator.cpp +++ b/contrib/nnc/passes/caffe2_frontend/caffe2_op_creator.cpp @@ -222,7 +222,7 @@ void Caffe2OpCreator::checkSpatialBN(const ::caffe2::OperatorDef& op, void Caffe2OpCreator::commonCheck(const ::caffe2::OperatorDef& op, std::set& problemsOpSet) { if (getSingleArgument(op, "order", "NCHW") != "NCHW") - problemsOpSet.insert("Only 'NCHW' oreder is supported"); + problemsOpSet.insert("Only 'NCHW' axis order is supported"); } // @@ -262,9 +262,8 @@ Caffe2OpCreator::convertAveragePool(const std::vector& inputs, std::vector pad_before, pad_after; std::tie(pad_before, pad_after) = getPadding(op); - auto pooling = createOp("Average_Pool", convertCaffeToMIR(inputs[0]), pool_type, window_shape, - strides, pad_before, pad_after, border_type, - ops::PoolOp::RoundMode::floor); + auto pooling = createOp("Average_Pool", convertCaffeToMIR(inputs[0]), pool_type, + window_shape, strides, pad_before, pad_after, border_type); return {convertMIRToCaffe(pooling->getOutput(0))}; } @@ -359,8 +358,7 @@ std::vector Caffe2OpCreator::convertMaxPool(const std::vector("Pool", convertCaffeToMIR(inputs[0]), pool_type, window_shape, - strides, pad_before, pad_after, border_type, - ops::PoolOp::RoundMode::floor); + strides, pad_before, pad_after, border_type); return {convertMIRToCaffe(pooling->getOutput(0))}; } diff --git a/contrib/nnc/passes/caffe_frontend/caffe_op_creator.cpp b/contrib/nnc/passes/caffe_frontend/caffe_op_creator.cpp index 423c8e4..d8323ea 100644 --- a/contrib/nnc/passes/caffe_frontend/caffe_op_creator.cpp +++ b/contrib/nnc/passes/caffe_frontend/caffe_op_creator.cpp @@ -347,8 +347,10 @@ static ops::PoolOp::PoolingType getPoolingType(const PoolingParameter& pool_para } static void convertPoolingParam(const caffe::PoolingParameter& pool_param, + const mir::Shape& input_shape, Shape& window_shape, Shape& strides, - std::vector& padding) { + std::vector& padding_before, + std::vector& padding_after) { int32_t kernel_h, kernel_w; assert(!pool_param.global_pooling()); if (pool_param.has_kernel_size()) { @@ -375,7 +377,14 @@ static void convertPoolingParam(const caffe::PoolingParameter& pool_param, } else { pad_h = pad_w = pool_param.pad(); } - padding = {pad_h, pad_w}; + + padding_before = padding_after = {pad_h, pad_w}; + // Since Caffe has incorrect pooling output shape formula, + // which leading to out-of-bound accesses - increase padding if needed + if ((input_shape.dim(2) + pad_h * 2 - window_shape.dim(0)) % stride_h != 0) + ++padding_after[0]; + if ((input_shape.dim(3) + pad_w * 2 - window_shape.dim(1)) % stride_w != 0) + ++padding_after[1]; } void CaffeOpCreator::checkPooling(const PoolingParameter& opts, @@ -397,9 +406,10 @@ CaffeOpCreator::convertPooling(const caffe::LayerParameter& layer, auto& opts = layer.pooling_param(); Shape window_shape; Shape strides; - std::vector padding; + std::vector padding_before, padding_after; - convertPoolingParam(opts, window_shape, strides, padding); + const auto& input_shape = inputs[0].op->getOutputShape(inputs[0].index); + convertPoolingParam(opts, input_shape, window_shape, strides, padding_before, padding_after); ops::PoolOp::PoolingType pool_type = getPoolingType(opts); ops::PoolOp::BorderType border_type; @@ -415,8 +425,8 @@ CaffeOpCreator::convertPooling(const caffe::LayerParameter& layer, } auto pooling = createOp(layer.name(), convertCaffeToMIR(inputs[0]), pool_type, - window_shape, strides, padding, padding, border_type, - ops::PoolOp::RoundMode::ceil); + window_shape, strides, padding_before, padding_after, + border_type); return {convertMIRToCaffe(pooling->getOutput(0))}; } diff --git a/contrib/nnc/passes/onnx_frontend/ONNXOpCreator.cpp b/contrib/nnc/passes/onnx_frontend/ONNXOpCreator.cpp index 32b9d25..fbc7e0b 100644 --- a/contrib/nnc/passes/onnx_frontend/ONNXOpCreator.cpp +++ b/contrib/nnc/passes/onnx_frontend/ONNXOpCreator.cpp @@ -279,10 +279,8 @@ ONNXOpCreator::convertPool(const std::vector& inputs, default: assert(false); } - auto result = createOp(t_input, pool_type, - cdata.kernel_shape, cdata.strides_shape, - cdata.padding_before, cdata.padding_after, - border_type, ops::PoolOp::RoundMode::floor); + auto result = createOp(t_input, pool_type, cdata.kernel_shape, cdata.strides_shape, + cdata.padding_before, cdata.padding_after, border_type); return {convertMIRToONNX(result->getOutput(0))}; } diff --git a/contrib/nnc/passes/tflite_frontend/tflite_op_creator.cpp b/contrib/nnc/passes/tflite_frontend/tflite_op_creator.cpp index 90b8ed6..3a5e53d 100644 --- a/contrib/nnc/passes/tflite_frontend/tflite_op_creator.cpp +++ b/contrib/nnc/passes/tflite_frontend/tflite_op_creator.cpp @@ -191,8 +191,7 @@ TFLiteOpCreator::convertMaxPool2D(const ::tflite::Pool2DOptions* opts, auto result = createOp(input, ops::PoolOp::PoolingType::MAX, window_shape, strides, padding_before, padding_after, - ops::PoolOp::BorderType::EMPTY, - ops::PoolOp::RoundMode::floor); + ops::PoolOp::BorderType::EMPTY); return {addFusedActivation(result->getOutput(0), opts->fused_activation_function())}; } @@ -212,8 +211,7 @@ TFLiteOpCreator::convertAveragePool2D(const ::tflite::Pool2DOptions* opts, auto result = createOp(input, ops::PoolOp::PoolingType::AVG, window_shape, strides, padding_before, padding_after, - ops::PoolOp::BorderType::EMPTY, - ops::PoolOp::RoundMode::floor); + ops::PoolOp::BorderType::EMPTY); return {addFusedActivation(result->getOutput(0), opts->fused_activation_function())}; } diff --git a/contrib/nnc/tests/interpreter/graph_creator.cpp b/contrib/nnc/tests/interpreter/graph_creator.cpp index f1fd0e0..d7f78ea 100644 --- a/contrib/nnc/tests/interpreter/graph_creator.cpp +++ b/contrib/nnc/tests/interpreter/graph_creator.cpp @@ -66,8 +66,7 @@ static Operation* createPool(std::unique_ptr& g, return g->create("y", inputs[0], getPoolingType(opInfo), getShapeParam(opInfo, 0), getShapeParam(opInfo, 1), std::vector{0, 0}, std::vector{0, 0}, - ops::PoolOp::BorderType::ZEROFILLED, - ops::PoolOp::RoundMode::floor); + ops::PoolOp::BorderType::ZEROFILLED); } static Operation* createConcatenation(std::unique_ptr& g, diff --git a/contrib/nnc/unittests/acl_backend/MIRToDOM.cpp b/contrib/nnc/unittests/acl_backend/MIRToDOM.cpp index a164827..3161cdf 100644 --- a/contrib/nnc/unittests/acl_backend/MIRToDOM.cpp +++ b/contrib/nnc/unittests/acl_backend/MIRToDOM.cpp @@ -402,8 +402,7 @@ TEST(acl_backend_mir_to_dom, maxpool) { std::vector padding{0, 0}; return g.create("maxPool", inputs[0], ops::PoolOp::PoolingType::MAX, window_shape, strides, padding, padding, - mir::ops::PoolOp::BorderType::EMPTY, - ops::PoolOp::RoundMode::floor); + mir::ops::PoolOp::BorderType::EMPTY); }; vector input_shapes{{1, 10, 10, 3}}; diff --git a/contrib/nnc/unittests/soft_backend/CPPOperations.cpp b/contrib/nnc/unittests/soft_backend/CPPOperations.cpp index cc07592..92f5f27 100644 --- a/contrib/nnc/unittests/soft_backend/CPPOperations.cpp +++ b/contrib/nnc/unittests/soft_backend/CPPOperations.cpp @@ -749,8 +749,7 @@ static mir::Operation* createPool(mir::Graph& g, irOps::PoolOp::BorderType border) { std::vector padding{0, 0}; return g.create("pool", inputs[0], poolT, window_shape, strides, - padding, padding, border, - irOps::PoolOp::RoundMode::floor); + padding, padding, border); }; template