From 9c606710319b085a5a4b0a604d1d9972f2ccb512 Mon Sep 17 00:00:00 2001 From: Nightingale Date: Fri, 28 May 2021 17:09:26 +0800 Subject: [PATCH] Add map for UnMaxpool2d (#83) Signed-off-by: zhao.xia --- include/tim/vx/ops/unmaxpool2d.h | 59 +++++++++++++++ src/tim/vx/ops/README.md | 2 +- src/tim/vx/ops/unmaxpool2d.cc | 46 ++++++++++++ src/tim/vx/ops/unmaxpool2d_test.cc | 116 +++++++++++++++++++++++++++++ 4 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 include/tim/vx/ops/unmaxpool2d.h create mode 100644 src/tim/vx/ops/unmaxpool2d.cc create mode 100644 src/tim/vx/ops/unmaxpool2d_test.cc diff --git a/include/tim/vx/ops/unmaxpool2d.h b/include/tim/vx/ops/unmaxpool2d.h new file mode 100644 index 0000000..a65b9d7 --- /dev/null +++ b/include/tim/vx/ops/unmaxpool2d.h @@ -0,0 +1,59 @@ +/**************************************************************************** +* +* Copyright (c) 2021 Vivante Corporation +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +* DEALINGS IN THE SOFTWARE. +* +*****************************************************************************/ +#ifndef TIM_VX_OPS_UNMAXPOOL2D_H_ +#define TIM_VX_OPS_UNMAXPOOL2D_H_ + +#include + +#include "tim/vx/operation.h" +#include "tim/vx/types.h" + +namespace tim { +namespace vx { +namespace ops { + +/** + * ## UnMaxpool2d + * + * Performs an 2-D Max pooling operation upsample + * + * - stride : stride along each spatial axis. + * - ksize : filter size. + */ + +class UnMaxpool2d : public Operation { + public: + UnMaxpool2d(Graph* graph, const std::array& ksize, + const std::array& stride, DataLayout layout = DataLayout::WHCN); + + protected: + const std::array ksize_; + const std::array stride_; +}; + +} // namespace ops +} // namespace vx +} // namespace tim + +#endif /* TIM_VX_OPS_UNMAXPOOL2D_H_ */ diff --git a/src/tim/vx/ops/README.md b/src/tim/vx/ops/README.md index 8dc5540..c91b8b2 100644 --- a/src/tim/vx/ops/README.md +++ b/src/tim/vx/ops/README.md @@ -18,7 +18,7 @@ DeConv2d|DECONVOLUTION|Mapped|[tf.nn.conv2d_transpose](https://tensorflow.google Reshape|RESHAPE|Mapped|[tf.reshape](https://tensorflow.google.cn/api_docs/python/tf/reshape) Transpose|PERMUTE|Mapped|[tf.transpose](https://tensorflow.google.cn/api_docs/python/tf/transpose) Prelu|PRELU|Mapped|[tf.keras.layers.PReLU](https://tensorflow.google.cn/api_docs/python/tf/keras/layers/PReLU) -||UPSAMPLE|Unmapped +UnMaxpool2d|UPSAMPLE|Mapped| Recover pixel from the outputs of MaxpoolWithArgmax. Relu|RELU|Mapped|[tf.nn.relu](https://tensorflow.google.cn/api_docs/python/tf/nn/relu) ||RELUN|Deprecated|[tf.keras.layers.ReLU(max_value=N)](https://tensorflow.google.cn/api_docs/python/tf/keras/layers/ReLU) Reorg|REORG|Mapped|[darknet.reorg](https://github.com/pjreddie/darknet/blob/master/src/reorg_layer.c) diff --git a/src/tim/vx/ops/unmaxpool2d.cc b/src/tim/vx/ops/unmaxpool2d.cc new file mode 100644 index 0000000..9da4166 --- /dev/null +++ b/src/tim/vx/ops/unmaxpool2d.cc @@ -0,0 +1,46 @@ +/**************************************************************************** +* +* Copyright (c) 2021 Vivante Corporation +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +* DEALINGS IN THE SOFTWARE. +* +*****************************************************************************/ +#include "tim/vx/ops/unmaxpool2d.h" + +#include "operation_private.h" +#include "type_utils.h" +#include "vsi_nn_pub.h" + +namespace tim { +namespace vx { +namespace ops { + +UnMaxpool2d::UnMaxpool2d(Graph* graph, const std::array& ksize, + const std::array& stride, DataLayout layout) + : Operation(graph, VSI_NN_OP_UPSAMPLE, 2, 1, layout), + ksize_(ksize), stride_(stride) { + this->impl()->node()->nn_param.upsample.scale[0] = stride_[0]; + this->impl()->node()->nn_param.upsample.scale[1] = stride_[1]; + this->impl()->node()->nn_param.upsample.size[0] = ksize_[0]; + this->impl()->node()->nn_param.upsample.size[1] = ksize_[1]; +} + +} // namespace ops +} // namespace vx +} // namespace tim diff --git a/src/tim/vx/ops/unmaxpool2d_test.cc b/src/tim/vx/ops/unmaxpool2d_test.cc new file mode 100644 index 0000000..61e3b45 --- /dev/null +++ b/src/tim/vx/ops/unmaxpool2d_test.cc @@ -0,0 +1,116 @@ +/**************************************************************************** +* +* Copyright (c) 2021 Vivante Corporation +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +* DEALINGS IN THE SOFTWARE. +* +*****************************************************************************/ +#include "tim/vx/context.h" +#include "tim/vx/graph.h" +#include "tim/vx/ops/unmaxpool2d.h" + +#include "gtest/gtest.h" + +TEST(UnMaxpool2d, shape_2_2_1_fp32_kernel_2_stride_2) { + auto ctx = tim::vx::Context::Create(); + auto graph = ctx->CreateGraph(); + + tim::vx::ShapeType in_shape({2, 2, 1}); + tim::vx::ShapeType out_shape({3, 3, 1}); + tim::vx::TensorSpec values_spec(tim::vx::DataType::FLOAT32, + in_shape, tim::vx::TensorAttribute::INPUT); + tim::vx::TensorSpec indices_spec(tim::vx::DataType::UINT8, + in_shape, tim::vx::TensorAttribute::INPUT); + tim::vx::TensorSpec output_spec(tim::vx::DataType::FLOAT32, + out_shape, tim::vx::TensorAttribute::OUTPUT); + + auto values_tensor = graph->CreateTensor(values_spec); + auto indices_tensor = graph->CreateTensor(indices_spec); + auto output_tensor = graph->CreateTensor(output_spec); + + std::vector values = { + 5, 6, + 8, 9 }; + std::vector indices = { + 3, 2, + 1, 0 }; + std::vector golden = { + 0, 0, 0, + 0, 5, 6, + 0, 8, 9 }; + + EXPECT_TRUE(values_tensor->CopyDataToTensor(values.data(), values.size()*4)); + EXPECT_TRUE(indices_tensor->CopyDataToTensor(indices.data(), indices.size()*4)); + std::array ksize = {2, 2}; + std::array stride = {2, 2}; + auto op = graph->CreateOperation(ksize, stride); + (*op).BindInputs({values_tensor, indices_tensor}).BindOutputs({output_tensor}); + + EXPECT_TRUE(graph->Compile()); + EXPECT_TRUE(graph->Run()); + std::vector output(golden.size()); + + EXPECT_TRUE(output_tensor->CopyDataFromTensor(output.data())); + EXPECT_EQ(golden, output); +} + +TEST(UnMaxpool2d, shape_2_2_1_uint8_kernel_2_stride_2) { + auto ctx = tim::vx::Context::Create(); + auto graph = ctx->CreateGraph(); + + tim::vx::ShapeType in_shape({2, 2, 1}); + tim::vx::ShapeType out_shape({4, 4, 1}); + tim::vx::Quantization io_quant(tim::vx::QuantType::ASYMMETRIC, 1, 0); + tim::vx::TensorSpec values_spec(tim::vx::DataType::UINT8, + in_shape, tim::vx::TensorAttribute::INPUT, io_quant); + tim::vx::TensorSpec indices_spec(tim::vx::DataType::UINT8, + in_shape, tim::vx::TensorAttribute::INPUT); + tim::vx::TensorSpec output_spec(tim::vx::DataType::UINT8, + out_shape, tim::vx::TensorAttribute::OUTPUT, io_quant); + + auto values_tensor = graph->CreateTensor(values_spec); + auto indices_tensor = graph->CreateTensor(indices_spec); + auto output_tensor = graph->CreateTensor(output_spec); + + std::vector values = { + 5, 6, + 11, 12}; + std::vector indices = { + 3, 2, + 3, 2}; + std::vector golden = { + 0, 0, 0, 0, + 0, 5, 6, 0, + 0, 0, 0, 0, + 0, 11, 12, 0 }; + + EXPECT_TRUE(values_tensor->CopyDataToTensor(values.data(), values.size())); + EXPECT_TRUE(indices_tensor->CopyDataToTensor(indices.data(), indices.size())); + std::array ksize = {2, 2}; + std::array stride = {2, 2}; + auto op = graph->CreateOperation(ksize, stride); + (*op).BindInputs({values_tensor, indices_tensor}).BindOutputs({output_tensor}); + + EXPECT_TRUE(graph->Compile()); + EXPECT_TRUE(graph->Run()); + std::vector output(golden.size()); + + EXPECT_TRUE(output_tensor->CopyDataFromTensor(output.data())); + EXPECT_EQ(golden, output); +}