From 1f0861840350a794de3e100f9f007b48bcb8b4c3 Mon Sep 17 00:00:00 2001 From: "yuenan.li" Date: Mon, 31 May 2021 10:00:38 +0800 Subject: [PATCH] Supprt layout inference for Operations Signed-off-by: yuenan.li --- include/tim/vx/ops/deconv.h | 18 ++- include/tim/vx/ops/reverse.h | 5 +- include/tim/vx/ops/split.h | 2 +- src/tim/transform/layout_inference.cc | 35 ++++- src/tim/transform/ops/arg_layout_inference.h | 88 ++++++++++++ .../transform/ops/conv2d_layout_inference.h | 23 +-- .../transform/ops/deconv2d_layout_inference.h | 136 ++++++++++++++++++ .../transform/ops/gather_layout_inference.h | 60 ++++++++ .../ops/gather_nd_layout_inference.h | 61 ++++++++ .../transform/ops/logical_layout_inference.h | 61 ++++++++ .../transform/ops/reverse_layout_inference.h | 61 ++++++++ .../transform/ops/select_layout_inference.h | 55 +++++++ .../ops/simple_ops_layout_inference.h | 1 - .../transform/ops/slice_layout_inference.h | 65 +++++++++ .../transform/ops/stack_layout_inference.h | 4 +- src/tim/vx/ops/deconv.cc | 16 ++- src/tim/vx/ops/reverse.cc | 8 +- 17 files changed, 669 insertions(+), 30 deletions(-) create mode 100644 src/tim/transform/ops/arg_layout_inference.h create mode 100644 src/tim/transform/ops/deconv2d_layout_inference.h create mode 100644 src/tim/transform/ops/gather_layout_inference.h create mode 100644 src/tim/transform/ops/gather_nd_layout_inference.h create mode 100644 src/tim/transform/ops/logical_layout_inference.h create mode 100644 src/tim/transform/ops/reverse_layout_inference.h create mode 100644 src/tim/transform/ops/select_layout_inference.h create mode 100644 src/tim/transform/ops/slice_layout_inference.h diff --git a/include/tim/vx/ops/deconv.h b/include/tim/vx/ops/deconv.h index ea919ac..ab7def4 100644 --- a/include/tim/vx/ops/deconv.h +++ b/include/tim/vx/ops/deconv.h @@ -40,13 +40,17 @@ namespace ops { * This operation is sometimes called "deconvolution" after Deconvolutional Networks, * but is actually the transpose (gradient) of Conv2D rather than an actual deconvolution. * - * - weights : the channel number for weight tensor. + * - oc_count_ : the out channel count for weight tensor. + * - pad_type : SAME, VALID or AUTO. * - ksize : the height and width for weight tensor. * - padding : AUTO, VALID or SAME. * - pad : pad value for each spatial axis. * - stride : stride along each spatial axis. * - output_padding : specifying the amount of padding along the height and width of * the output tensor. + * - group : the feature count of each group. + * - input_layout : Layout for input, WHCN by default. + * - kernel_layout: Layout for kernel, WHIO by default. */ class DeConv2d : public Operation { @@ -54,22 +58,28 @@ class DeConv2d : public Operation { DeConv2d(Graph* graph, int32_t oc_count_, PadType pad_type, const std::array& ksize, const std::array& stride, - const std::array& output_padding); + const std::array& output_padding, + DataLayout input_layout = DataLayout::WHCN, + DataLayout kernel_layout = DataLayout::WHIcOc); DeConv2d(Graph* graph, int32_t oc_count_, PadType pad_type, const std::array& ksize, const std::array& stride, const std::array& output_padding, const std::array& pad, - const uint32_t group = 1); + const uint32_t group = 1, + DataLayout input_layout = DataLayout::WHCN, + DataLayout kernel_layout = DataLayout::WHIcOc); + DataLayout KernelDataLayout() { return kernel_layout_; } protected: - const uint32_t oc_count_; // output channel count + const uint32_t oc_count_; const PadType pad_type_; const std::array ksize_; const std::array stride_; const std::array output_padding_; const std::array pad_; const uint32_t group_; + const DataLayout kernel_layout_; }; } // namespace ops diff --git a/include/tim/vx/ops/reverse.h b/include/tim/vx/ops/reverse.h index abfc82e..69c9bef 100644 --- a/include/tim/vx/ops/reverse.h +++ b/include/tim/vx/ops/reverse.h @@ -39,11 +39,10 @@ namespace ops { class Reverse : public Operation { public: - Reverse(Graph* graph, int32_t* axis, uint32_t axis_num); + Reverse(Graph* graph, const std::vector& axis); protected: - int32_t* axis_; - uint32_t axis_num_; + const std::vector axis_; }; } // namespace ops diff --git a/include/tim/vx/ops/split.h b/include/tim/vx/ops/split.h index ee5db22..0359aca 100644 --- a/include/tim/vx/ops/split.h +++ b/include/tim/vx/ops/split.h @@ -37,7 +37,7 @@ namespace ops { * Splits a tensor along a given axis into num_splits subtensors. * * - axis : the axis along which to split. - * - slices : ndicating the number of splits along given axis. + * - slices : indicating the number of splits along given axis. */ class Split : public Operation { diff --git a/src/tim/transform/layout_inference.cc b/src/tim/transform/layout_inference.cc index 2b290be..b64e8b3 100644 --- a/src/tim/transform/layout_inference.cc +++ b/src/tim/transform/layout_inference.cc @@ -50,6 +50,14 @@ #include "ops/lrn_layout_inference.h" #include "ops/l2normalization_layout_inference.h" #include "ops/addn_layout_inference.h" +#include "ops/gather_layout_inference.h" +#include "ops/gather_nd_layout_inference.h" +#include "ops/reverse_layout_inference.h" +#include "ops/slice_layout_inference.h" +#include "ops/select_layout_inference.h" +#include "ops/logical_layout_inference.h" +#include "ops/arg_layout_inference.h" +#include "ops/deconv2d_layout_inference.h" #include #include @@ -149,7 +157,7 @@ void LayoutInferContext::UpdateGraphInputMap(const std::shared_ptr& break; \ } \ -#define REGIST_REDUCE_LAYOUT_INFERENCE(op_idx) \ +#define REGIST_REDUCE_LAYOUT_INFERENCE(op_idx) \ case op_idx: { \ auto reduce_type = op->impl()->node()->nn_param.reduce.type; \ switch (reduce_type) { \ @@ -166,6 +174,20 @@ void LayoutInferContext::UpdateGraphInputMap(const std::shared_ptr& break; \ } \ +#define REGIST_LOGICAL_LAYOUT_INFERENCE(op_idx) \ + case op_idx: { \ + auto logical_type = op->impl()->node()->nn_param.relational_ops.op; \ + switch (logical_type) \ + { \ + REGIST_LAYOUT_INFERENCE(VSI_NN_LOGICAL_AND, LogicalAnd); \ + REGIST_LAYOUT_INFERENCE(VSI_NN_LOGICAL_OR, LogicalOr); \ + default: \ + VSILOGW("Op %d: Default layout inference pass for logical.", logical_type);\ + assert(false); \ + } \ + break; \ + } \ + std::vector> HandleLayoutInfer( std::shared_ptr& ctx, const std::shared_ptr& op) { @@ -213,7 +235,6 @@ std::vector> HandleLayoutInfer( REGIST_LAYOUT_INFERENCE(VSI_NN_OP_SPACE2BATCH, SpaceToBatch); REGIST_LAYOUT_INFERENCE(VSI_NN_OP_BATCH2SPACE, BatchToSpace); REGIST_LAYOUT_INFERENCE(VSI_NN_OP_PAD, Pad); - REGIST_REDUCE_LAYOUT_INFERENCE(VSI_NN_OP_REDUCE); REGIST_LAYOUT_INFERENCE(VSI_NN_OP_FCL2, FullyConnected); REGIST_LAYOUT_INFERENCE(VSI_NN_OP_RESIZE, Resize); REGIST_LAYOUT_INFERENCE(VSI_NN_OP_SPLIT, Split); @@ -222,6 +243,16 @@ std::vector> HandleLayoutInfer( REGIST_LAYOUT_INFERENCE(VSI_NN_OP_L2_NORMALIZE, L2Normalization); REGIST_LAYOUT_INFERENCE(VSI_NN_OP_ADDN, AddN); REGIST_LAYOUT_INFERENCE(VSI_NN_OP_PRELU, PRelu); + REGIST_LAYOUT_INFERENCE(VSI_NN_OP_GATHER, Gather); + REGIST_LAYOUT_INFERENCE(VSI_NN_OP_GATHER_ND, GatherNd); + REGIST_LAYOUT_INFERENCE(VSI_NN_OP_REVERSE, Reverse); + REGIST_LAYOUT_INFERENCE(VSI_NN_OP_SLICE, Slice); + REGIST_LAYOUT_INFERENCE(VSI_NN_OP_SELECT, Select); + REGIST_LAYOUT_INFERENCE(VSI_NN_OP_ARGMAX, ArgMax); + REGIST_LAYOUT_INFERENCE(VSI_NN_OP_ARGMIN, ArgMin); + REGIST_LAYOUT_INFERENCE(VSI_NN_OP_DECONVOLUTION, DeConv2d); + REGIST_LOGICAL_LAYOUT_INFERENCE(VSI_NN_OP_LOGICAL_OPS); + REGIST_REDUCE_LAYOUT_INFERENCE(VSI_NN_OP_REDUCE); default: VSILOGW("Op %d: Default layout inference pass.", op_id); assert(false); diff --git a/src/tim/transform/ops/arg_layout_inference.h b/src/tim/transform/ops/arg_layout_inference.h new file mode 100644 index 0000000..618de29 --- /dev/null +++ b/src/tim/transform/ops/arg_layout_inference.h @@ -0,0 +1,88 @@ +/**************************************************************************** + * + * Copyright (c) 2020 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_LAYOUT_INFER_ARG_OPS_LAYOUT_INFERENCE_H_ +#define TIM_LAYOUT_INFER_ARG_OPS_LAYOUT_INFERENCE_H_ + +#include "src/tim/transform/ops/op_layout_inference.h" +#include "src/tim/vx/operation_private.h" +#include "tim/vx/ops/arg.h" +namespace tim { +namespace transform { +class ArgMaxLayoutInfer : public OpLayoutInfer { + public: + ArgMaxLayoutInfer( + const std::shared_ptr op, + std::shared_ptr& context) + : OpLayoutInfer(op, context) {} + + void OnInputs( + std::vector>& next_tensors) override { + assert(1 == op_->impl()->InputsTensor().size()); + auto src_input = op_->impl()->InputsTensor()[0]; + auto input_pv = context_->GetPermuteVector(src_input); + + uint32_t axis = op_->impl()->node()->nn_param.argmax.axis; + axis = MapAxis(input_pv->AsStdVec(), axis); + + auto argmax = + context_->infer_graph_->CreateOperation(axis); + auto infer_out = CreateOutputsTensor(input_pv); + (*argmax).BindInput(context_->GetMapedTensor(src_input)); + (*argmax).BindOutput(infer_out[0]); + + context_->SetPermuteVector(op_->impl()->OutputsTensor()[0], input_pv); + next_tensors.push_back(op_->impl()->OutputsTensor()[0]); + } +}; + +class ArgMinLayoutInfer : public OpLayoutInfer { + public: + ArgMinLayoutInfer( + const std::shared_ptr op, + std::shared_ptr& context) + : OpLayoutInfer(op, context) {} + + void OnInputs( + std::vector>& next_tensors) override { + assert(1 == op_->impl()->InputsTensor().size()); + auto src_input = op_->impl()->InputsTensor()[0]; + auto input_pv = context_->GetPermuteVector(src_input); + + uint32_t axis = op_->impl()->node()->nn_param.argmin.axis; + axis = MapAxis(input_pv->AsStdVec(), axis); + + auto argmin = + context_->infer_graph_->CreateOperation(axis); + auto infer_out = CreateOutputsTensor(input_pv); + (*argmin).BindInput(context_->GetMapedTensor(src_input)); + (*argmin).BindOutput(infer_out[0]); + + context_->SetPermuteVector(op_->impl()->OutputsTensor()[0], input_pv); + next_tensors.push_back(op_->impl()->OutputsTensor()[0]); + } +}; + +} // namespace transform +} // namespace tim +#endif \ No newline at end of file diff --git a/src/tim/transform/ops/conv2d_layout_inference.h b/src/tim/transform/ops/conv2d_layout_inference.h index 6ddef10..1c47977 100644 --- a/src/tim/transform/ops/conv2d_layout_inference.h +++ b/src/tim/transform/ops/conv2d_layout_inference.h @@ -78,15 +78,22 @@ class Conv2dLayoutInfer : public OpLayoutInfer { } } } else { - // For input/weight - auto pv = context_->GetPermuteVector(in); - auto final_pv = pv->Reverse()->Add(required_pv); - if (!final_pv->IsAligned()) { - infer_tensor = InsertPermute(context_->GetMapedTensor(in), final_pv); - trans_pv = required_pv; - } else { + // For bias + if (in->GetShape().size() == 1) { infer_tensor = context_->GetMapedTensor(in); - trans_pv = pv; + trans_pv = MakeShared(1); + } else { + // For input/weight + auto pv = context_->GetPermuteVector(in); + auto final_pv = pv->Reverse()->Add(required_pv); + if (!final_pv->IsAligned()) { + infer_tensor = + InsertPermute(context_->GetMapedTensor(in), final_pv); + trans_pv = required_pv; + } else { + infer_tensor = context_->GetMapedTensor(in); + trans_pv = pv; + } } } context_->UpdateTensorMap(in, infer_tensor); diff --git a/src/tim/transform/ops/deconv2d_layout_inference.h b/src/tim/transform/ops/deconv2d_layout_inference.h new file mode 100644 index 0000000..4343437 --- /dev/null +++ b/src/tim/transform/ops/deconv2d_layout_inference.h @@ -0,0 +1,136 @@ +/**************************************************************************** + * + * Copyright (c) 2020 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_LAYOUT_INFER_DECONV2D_LAYOUT_INFERENCE_H_ +#define TIM_LAYOUT_INFER_DECONV2D_LAYOUT_INFERENCE_H_ + +#include "src/tim/transform/ops/op_layout_inference.h" +#include "src/tim/transform/permute_vector.h" +#include "src/tim/vx/operation_private.h" +#include "tim/vx/ops/deconv.h" + +namespace tim { +namespace transform { +class DeConv2dLayoutInfer : public OpLayoutInfer { + public: + DeConv2dLayoutInfer( + const std::shared_ptr& op, + std::shared_ptr& context) + : OpLayoutInfer(op, context) {} + + void OnInputs( + std::vector>& next_tensors) override { + vx::DataLayout layout = op_->impl()->layout_; + auto required_pv = MakeShared(4); + if (layout == vx::DataLayout::CWHN) { + required_pv = std::make_shared>(kCWHN2WHCN); + } + auto src_inputs = op_->impl()->InputsTensor(); + + for (const auto& in : src_inputs) { + std::shared_ptr infer_tensor; + std::shared_ptr trans_pv; + if (in->IsConstTensor() && + !(in->GetSpec().attr_ & vx::TensorAttribute::INPUT)) { + // For bias + if (in->GetShape().size() == 1) { + infer_tensor = context_->infer_graph_->CreateTensor(in->GetSpec(), + in->GetDataRef()); + trans_pv = MakeShared(1); + } else { + // For input/weight + if (!required_pv->IsAligned()) { + auto src_deconv2d = + std::static_pointer_cast(op_); + // Support TVM Kernel Layout + if (src_deconv2d->KernelDataLayout() == vx::DataLayout::OcIcWH) { + trans_pv = std::make_shared>(kOcIcWH2WHIcOc); + infer_tensor = PermuteConstTensor(in, trans_pv); + } else { + infer_tensor = PermuteConstTensor(in, required_pv); + trans_pv = required_pv; + } + } else { + infer_tensor = context_->infer_graph_->CreateTensor( + in->GetSpec(), in->GetDataRef()); + trans_pv = MakeShared(required_pv->Rank()); + } + } + } else { + // For bias + if (in->GetShape().size() == 1) { + infer_tensor = context_->GetMapedTensor(in); + trans_pv = MakeShared(1); + } else { + // For input/weight + auto pv = context_->GetPermuteVector(in); + auto final_pv = pv->Reverse()->Add(required_pv); + if (!final_pv->IsAligned()) { + infer_tensor = + InsertPermute(context_->GetMapedTensor(in), final_pv); + trans_pv = required_pv; + } else { + infer_tensor = context_->GetMapedTensor(in); + trans_pv = pv; + } + } + } + context_->UpdateTensorMap(in, infer_tensor); + context_->SetPermuteVector(in, trans_pv); + } + + auto pad_type = + TranslatePadType(op_->impl()->node()->nn_param.deconv.pad_type); + std::array ksize = { + op_->impl()->node()->nn_param.deconv.ksize[0], + op_->impl()->node()->nn_param.deconv.ksize[1]}; + std::array stride = { + op_->impl()->node()->nn_param.deconv.stride[0], + op_->impl()->node()->nn_param.deconv.stride[1]}; + std::array output_padding = { + op_->impl()->node()->nn_param.deconv.output_padding[0], + op_->impl()->node()->nn_param.deconv.output_padding[0]}; + std::array pad = {op_->impl()->node()->nn_param.deconv.pad[0], + op_->impl()->node()->nn_param.deconv.pad[1], + op_->impl()->node()->nn_param.deconv.pad[2], + op_->impl()->node()->nn_param.deconv.pad[3]}; + int32_t oc_count = op_->impl()->node()->nn_param.deconv.weights; + const uint32_t group = op_->impl()->node()->nn_param.deconv.group; + + auto deconv = context_->infer_graph_->CreateOperation( + oc_count, pad_type, ksize, stride, output_padding, pad, group); + auto infer_out = CreateOutputsTensor(required_pv); + for (const auto& i_src : src_inputs) { + (*deconv).BindInput(context_->GetMapedTensor(i_src)); + } + (*deconv).BindOutput(infer_out[0]); + + context_->SetPermuteVector(op_->impl()->OutputsTensor()[0], required_pv); + next_tensors.push_back(op_->impl()->OutputsTensor()[0]); + } +}; + +} // namespace transform +} // namespace tim + +#endif \ No newline at end of file diff --git a/src/tim/transform/ops/gather_layout_inference.h b/src/tim/transform/ops/gather_layout_inference.h new file mode 100644 index 0000000..4294588 --- /dev/null +++ b/src/tim/transform/ops/gather_layout_inference.h @@ -0,0 +1,60 @@ +/**************************************************************************** + * + * Copyright (c) 2020 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_LAYOUT_INFER_GATHER_LAYOUT_INFERENCE_H_ +#define TIM_LAYOUT_INFER_GATHER_LAYOUT_INFERENCE_H_ + +#include "src/tim/transform/ops/op_layout_inference.h" +#include "src/tim/vx/operation_private.h" +#include "tim/vx/ops/gather.h" + +namespace tim { +namespace transform { +class GatherLayoutInfer : public OpLayoutInfer { + public: + GatherLayoutInfer( + const std::shared_ptr& op, + std::shared_ptr& context) + : OpLayoutInfer(op, context) {} + void OnInputs( + std::vector>& next_tensors) override { + ReverseInputsPermuteVector(); + + auto gather = context_->infer_graph_->CreateOperation( + op_->impl()->node()->nn_param.gather.axis); + int32_t output_rank = -1; + for (const auto& i_src : op_->impl()->InputsTensor()) { + (*gather).BindInput(context_->GetMapedTensor(i_src)); + output_rank += i_src->GetShape().size(); + } + auto infer_out = CreateOutputsTensor( + context_->GetPermuteVector(op_->impl()->InputsTensor()[0])); + (*gather).BindOutput(infer_out[0]); + auto output_pv = MakeShared(output_rank); + context_->SetPermuteVector(op_->impl()->OutputsTensor()[0], output_pv); + next_tensors.push_back(op_->impl()->OutputsTensor()[0]); + } +}; +} // namespace transform +} // namespace tim +#endif \ No newline at end of file diff --git a/src/tim/transform/ops/gather_nd_layout_inference.h b/src/tim/transform/ops/gather_nd_layout_inference.h new file mode 100644 index 0000000..c70ec17 --- /dev/null +++ b/src/tim/transform/ops/gather_nd_layout_inference.h @@ -0,0 +1,61 @@ +/**************************************************************************** + * + * Copyright (c) 2020 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_LAYOUT_INFER_GATHER_ND_LAYOUT_INFERENCE_H_ +#define TIM_LAYOUT_INFER_GATHER_ND_LAYOUT_INFERENCE_H_ + +#include "src/tim/transform/ops/op_layout_inference.h" +#include "src/tim/vx/operation_private.h" +#include "tim/vx/ops/gathernd.h" + +namespace tim { +namespace transform { +class GatherNdLayoutInfer : public OpLayoutInfer { + public: + GatherNdLayoutInfer( + const std::shared_ptr& op, + std::shared_ptr& context) + : OpLayoutInfer(op, context) {} + void OnInputs( + std::vector>& next_tensors) override { + ReverseInputsPermuteVector(); + uint32_t input_rank = op_->impl()->InputsTensor()[0]->GetShape().size(); + uint32_t position_rank = op_->impl()->InputsTensor()[1]->GetShape().size(); + uint32_t indices_rank = op_->impl()->InputsTensor()[1]->GetShape()[0]; + int32_t output_rank = input_rank + position_rank - indices_rank - 1; + + auto gather = context_->infer_graph_->CreateOperation(); + for (const auto& i_src : op_->impl()->InputsTensor()) { + (*gather).BindInput(context_->GetMapedTensor(i_src)); + } + auto infer_out = CreateOutputsTensor( + context_->GetPermuteVector(op_->impl()->InputsTensor()[0])); + (*gather).BindOutput(infer_out[0]); + auto output_pv = MakeShared(output_rank); + context_->SetPermuteVector(op_->impl()->OutputsTensor()[0], output_pv); + next_tensors.push_back(op_->impl()->OutputsTensor()[0]); + } +}; +} // namespace transform +} // namespace tim +#endif \ No newline at end of file diff --git a/src/tim/transform/ops/logical_layout_inference.h b/src/tim/transform/ops/logical_layout_inference.h new file mode 100644 index 0000000..f9885c1 --- /dev/null +++ b/src/tim/transform/ops/logical_layout_inference.h @@ -0,0 +1,61 @@ +/**************************************************************************** + * + * Copyright (c) 2020 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_LAYOUT_INFER_LOGICAL_OPS_LAYOUT_INFERENCE_H_ +#define TIM_LAYOUT_INFER_LOGICAL_OPS_LAYOUT_INFERENCE_H_ + +#include "src/tim/transform/ops/op_layout_inference.h" +#include "src/tim/vx/operation_private.h" +#include "tim/vx/ops/logical.h" + +namespace tim { +namespace transform { +template +class LogicalOpsLayoutInfer : public OpLayoutInfer { + public: + LogicalOpsLayoutInfer( + const std::shared_ptr op, + std::shared_ptr& context) + : OpLayoutInfer(op, context) {} + + void OnInputs( + std::vector>& next_tensors) override { + auto required_pv = AlignPermuteVectorForMutilInputs(); + auto infer_out = CreateOutputsTensor(required_pv); + auto logical_op = context_->infer_graph_->CreateOperation(); + for (const auto& i_src : op_->impl()->InputsTensor()) { + (*logical_op).BindInput(context_->GetMapedTensor(i_src)); + } + (*logical_op).BindOutput(infer_out[0]); + + context_->SetPermuteVector(op_->impl()->OutputsTensor()[0], required_pv); + next_tensors.push_back(op_->impl()->OutputsTensor()[0]); + } +}; + +using LogicalAndLayoutInfer = LogicalOpsLayoutInfer; +using LogicalOrLayoutInfer = LogicalOpsLayoutInfer; + +} // namespace transform +} // namespace tim +#endif \ No newline at end of file diff --git a/src/tim/transform/ops/reverse_layout_inference.h b/src/tim/transform/ops/reverse_layout_inference.h new file mode 100644 index 0000000..abfc412 --- /dev/null +++ b/src/tim/transform/ops/reverse_layout_inference.h @@ -0,0 +1,61 @@ +/**************************************************************************** + * + * Copyright (c) 2020 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_LAYOUT_INFER_REVERSE_LAYOUT_INFERENCE_H_ +#define TIM_LAYOUT_INFER_REVERSE_LAYOUT_INFERENCE_H_ + +#include "src/tim/transform/ops/op_layout_inference.h" +#include "src/tim/vx/operation_private.h" +#include "tim/vx/ops/reverse.h" + +namespace tim { +namespace transform { +class ReverseLayoutInfer : public OpLayoutInfer { + public: + ReverseLayoutInfer( + const std::shared_ptr& op, + std::shared_ptr& context) + : OpLayoutInfer(op, context) {} + void OnInputs( + std::vector>& next_tensors) override { + auto src_input = op_->impl()->InputsTensor()[0]; + auto input_pv = context_->GetPermuteVector(src_input); + std::vector axis(op_->impl()->node()->nn_param.reverse.axis_num); + memcpy(axis.data(), op_->impl()->node()->nn_param.reverse.axis, + axis.size() * sizeof(int32_t)); + for (uint32_t i = 0; i < axis.size(); ++i) { + axis[i] = MapAxis(input_pv->AsStdVec(), axis[i]); + } + + auto reverse = context_->infer_graph_->CreateOperation( + axis); + (*reverse).BindInput(context_->GetMapedTensor(src_input)); + auto infer_out = CreateOutputsTensor(input_pv); + (*reverse).BindOutput(infer_out[0]); + context_->SetPermuteVector(op_->impl()->OutputsTensor()[0], input_pv); + next_tensors.push_back(op_->impl()->OutputsTensor()[0]); + } +}; +} // namespace transform +} // namespace tim +#endif \ No newline at end of file diff --git a/src/tim/transform/ops/select_layout_inference.h b/src/tim/transform/ops/select_layout_inference.h new file mode 100644 index 0000000..3fbde95 --- /dev/null +++ b/src/tim/transform/ops/select_layout_inference.h @@ -0,0 +1,55 @@ +/**************************************************************************** + * + * Copyright (c) 2020 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_LAYOUT_INFER_SELECT_LAYOUT_INFERENCE_H_ +#define TIM_LAYOUT_INFER_SELECT_LAYOUT_INFERENCE_H_ + +#include "src/tim/transform/ops/op_layout_inference.h" +#include "src/tim/vx/operation_private.h" +#include "tim/vx/ops/select.h" + +namespace tim { +namespace transform { +class SelectLayoutInfer : public OpLayoutInfer { + public: + SelectLayoutInfer( + const std::shared_ptr& op, + std::shared_ptr& context) + : OpLayoutInfer(op, context) {} + void OnInputs( + std::vector>& next_tensors) override { + auto required_pv = AlignPermuteVectorForMutilInputs(); + auto select = context_->infer_graph_->CreateOperation(); + auto infer_out = CreateOutputsTensor(required_pv); + for (const auto& i_src : op_->impl()->InputsTensor()) { + (*select).BindInput(context_->GetMapedTensor(i_src)); + } + (*select).BindOutput(infer_out[0]); + + context_->SetPermuteVector(op_->impl()->OutputsTensor()[0], required_pv); + next_tensors.push_back(op_->impl()->OutputsTensor()[0]); + } +}; +} // namespace transform +} // namespace tim +#endif \ No newline at end of file diff --git a/src/tim/transform/ops/simple_ops_layout_inference.h b/src/tim/transform/ops/simple_ops_layout_inference.h index e8d2545..90c953d 100644 --- a/src/tim/transform/ops/simple_ops_layout_inference.h +++ b/src/tim/transform/ops/simple_ops_layout_inference.h @@ -69,7 +69,6 @@ using RsqrtLayoutInfer = SimpleOpsLayoutInfer; using SquareLayoutInfer = SimpleOpsLayoutInfer; using LogicalNotLayoutInfer = SimpleOpsLayoutInfer; - } // namespace transform } // namespace tim diff --git a/src/tim/transform/ops/slice_layout_inference.h b/src/tim/transform/ops/slice_layout_inference.h new file mode 100644 index 0000000..1b15f94 --- /dev/null +++ b/src/tim/transform/ops/slice_layout_inference.h @@ -0,0 +1,65 @@ +/**************************************************************************** + * + * Copyright (c) 2020 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_LAYOUT_INFER_SLICE_LAYOUT_INFERENCE_H_ +#define TIM_LAYOUT_INFER_SLICE_LAYOUT_INFERENCE_H_ + +#include "src/tim/transform/ops/op_layout_inference.h" +#include "src/tim/vx/operation_private.h" +#include "tim/vx/ops/slice.h" + +namespace tim { +namespace transform { +class SliceLayoutInfer : public OpLayoutInfer { + public: + SliceLayoutInfer( + const std::shared_ptr& op, + std::shared_ptr& context) + : OpLayoutInfer(op, context) {} + void OnInputs( + std::vector>& next_tensors) override { + auto src_input = op_->impl()->InputsTensor()[0]; + auto input_pv = context_->GetPermuteVector(src_input); + + uint32_t dims = op_->impl()->node()->nn_param.slice.dims; + const uint32_t* start_ptr = op_->impl()->node()->nn_param.slice.start; + const uint32_t* length_ptr = op_->impl()->node()->nn_param.slice.length; + std::vector start(dims); + std::vector length(dims); + memcpy(start.data(), start_ptr, dims * sizeof(uint32_t)); + memcpy(length.data(), length_ptr, dims * sizeof(uint32_t)); + start = MapMultipleAxis(input_pv->AsStdVec(), start); + length = MapMultipleAxis(input_pv->AsStdVec(), length); + + auto slice = context_->infer_graph_->CreateOperation( + dims, start, length); + auto infer_out = CreateOutputsTensor(input_pv); + (*slice).BindInput(context_->GetMapedTensor(src_input)); + (*slice).BindOutput(infer_out[0]); + context_->SetPermuteVector(op_->impl()->OutputsTensor()[0], input_pv); + next_tensors.push_back(op_->impl()->OutputsTensor()[0]); + } +}; +} // namespace transform +} // namespace tim +#endif \ No newline at end of file diff --git a/src/tim/transform/ops/stack_layout_inference.h b/src/tim/transform/ops/stack_layout_inference.h index 4637649..7df6dba 100644 --- a/src/tim/transform/ops/stack_layout_inference.h +++ b/src/tim/transform/ops/stack_layout_inference.h @@ -45,7 +45,9 @@ class StackLayoutInfer : public OpLayoutInfer { int32_t axis = op_->impl()->node()->nn_param.stack.axis; auto stack = context_->infer_graph_->CreateOperation( axis, op_->impl()->input_cnt_); - (*stack).BindInput(context_->GetMapedTensor(op_->impl()->InputsTensor()[0])); + for (const auto& i_src : op_->impl()->InputsTensor()) { + (*stack).BindInput(context_->GetMapedTensor(i_src)); + } auto required_pv = MakeShared(op_->impl()->OutputsTensor()[0]->GetShape().size()); auto out_infer = CreateOutputsTensor(required_pv); (*stack).BindOutput(out_infer[0]); diff --git a/src/tim/vx/ops/deconv.cc b/src/tim/vx/ops/deconv.cc index 7643e90..ca1f554 100644 --- a/src/tim/vx/ops/deconv.cc +++ b/src/tim/vx/ops/deconv.cc @@ -36,25 +36,29 @@ namespace ops { DeConv2d::DeConv2d(Graph* graph, int32_t oc_count, PadType pad_type, const std::array& ksize, const std::array& stride, - const std::array& output_padding) + const std::array& output_padding, + DataLayout input_layout, + DataLayout kernel_layout) : DeConv2d(graph, oc_count, pad_type, ksize, stride, output_padding, - {0, 0, 0, 0}) { -} + {0, 0, 0, 0}, 1, input_layout, kernel_layout) {} DeConv2d::DeConv2d(Graph* graph, int32_t oc_count, PadType pad_type, const std::array& ksize, const std::array& stride, const std::array& output_padding, const std::array& pad, - const uint32_t group) - : Operation(graph, VSI_NN_OP_DECONVOLUTION), + const uint32_t group, + DataLayout input_layout, + DataLayout kernel_layout) + : Operation(graph, VSI_NN_OP_DECONVOLUTION, 0, 0, input_layout), oc_count_(oc_count), pad_type_(pad_type), ksize_(ksize), stride_(stride), output_padding_(output_padding), pad_(pad), - group_(group) { + group_(group), + kernel_layout_(kernel_layout) { // TODO(Sven): only support depthwise usage assert((group == 1U) || group == static_cast(oc_count)); diff --git a/src/tim/vx/ops/reverse.cc b/src/tim/vx/ops/reverse.cc index e61e541..9a086d6 100644 --- a/src/tim/vx/ops/reverse.cc +++ b/src/tim/vx/ops/reverse.cc @@ -30,10 +30,10 @@ namespace tim { namespace vx { namespace ops { -Reverse::Reverse(Graph* graph, int32_t* axis, uint32_t axis_num) - : Operation(graph, VSI_NN_OP_REVERSE), axis_(axis), axis_num_(axis_num) { - this->impl()->node()->nn_param.reverse.axis = axis_; - this->impl()->node()->nn_param.reverse.axis_num = axis_num_; +Reverse::Reverse(Graph* graph, const std::vector& axis) + : Operation(graph, VSI_NN_OP_REVERSE), axis_(axis) { + this->impl()->node()->nn_param.reverse.axis = axis_.data(); + this->impl()->node()->nn_param.reverse.axis_num = axis_.size(); } } // namespace ops } // namespace vx