blob: 5cd906da41a760b9cbe6d2cebf0f287fa5ab4d39 [file] [log] [blame]
Nikhil Raj8599a412018-11-19 14:51:07 +00001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
Jim Flynn39d487d2019-05-17 15:44:36 +01006#include "NeonConcatWorkload.hpp"
Matthew Benthamd80a7122019-01-08 17:52:37 +00007
8#include "NeonWorkloadUtils.hpp"
9
Nikhil Raj8599a412018-11-19 14:51:07 +000010#include <aclCommon/ArmComputeTensorUtils.hpp>
Jan Eilers3c9e0452020-04-10 13:00:44 +010011#include <armnn/utility/PolymorphicDowncast.hpp>
James Conroy1f58f032021-04-27 17:13:27 +010012#include <backendsCommon/TensorHandle.hpp>
Nikhil Raj8599a412018-11-19 14:51:07 +000013#include <neon/NeonTensorHandle.hpp>
14
Nikhil Raj8599a412018-11-19 14:51:07 +000015namespace armnn
16{
17using namespace armcomputetensorutils;
18
Derek Lamberti0790dce2019-04-15 18:37:35 +010019namespace
20{
Jim Flynne242f2d2019-05-22 14:24:13 +010021size_t CalcAxis(const armnn::OriginsDescriptor& desc)
Derek Lamberti0790dce2019-04-15 18:37:35 +010022{
23 return (desc.GetNumDimensions() - desc.GetConcatAxis()) - 1;
24}
25} //namespace
26
Jim Flynn39d487d2019-05-17 15:44:36 +010027arm_compute::Status NeonConcatWorkloadValidate(const std::vector<const TensorInfo*>& inputs,
Nikhil Raj8599a412018-11-19 14:51:07 +000028 const TensorInfo& output,
Jim Flynne242f2d2019-05-22 14:24:13 +010029 const OriginsDescriptor& descriptor)
Nikhil Raj8599a412018-11-19 14:51:07 +000030
31{
32 std::vector<arm_compute::TensorInfo> aclInputs;
33 for (const TensorInfo* input : inputs)
34 {
Derek Lamberti0790dce2019-04-15 18:37:35 +010035 arm_compute::TensorInfo aclInputInfo = BuildArmComputeTensorInfo(*input, armnn::DataLayout::NCHW);
36 aclInputs.emplace_back(aclInputInfo);
Nikhil Raj8599a412018-11-19 14:51:07 +000037 }
38 const arm_compute::TensorInfo aclOutputInfo = BuildArmComputeTensorInfo(output);
Teresa Charlin552ee4d2020-07-16 12:44:16 +010039 std::vector<const arm_compute::ITensorInfo*> aclInputPtrs;
Nikhil Raj8599a412018-11-19 14:51:07 +000040 for (arm_compute::ITensorInfo& input : aclInputs)
41 {
42 aclInputPtrs.emplace_back(&input);
43 }
44
Derek Lamberti0790dce2019-04-15 18:37:35 +010045 size_t aclAxis = CalcAxis(descriptor);
Nikhil Raj8599a412018-11-19 14:51:07 +000046 return arm_compute::NEConcatenateLayer::validate(aclInputPtrs, &aclOutputInfo, aclAxis);
Nikhil Raj8599a412018-11-19 14:51:07 +000047}
48
Jim Flynn39d487d2019-05-17 15:44:36 +010049NeonConcatWorkload::NeonConcatWorkload(
Jim Flynne242f2d2019-05-22 14:24:13 +010050const ConcatQueueDescriptor& descriptor, const WorkloadInfo& info)
51 : BaseWorkload<ConcatQueueDescriptor>(descriptor, info)
Nikhil Raj8599a412018-11-19 14:51:07 +000052{
Derek Lamberti0790dce2019-04-15 18:37:35 +010053 bool allInputsAreSubtensors = true;
Nikhil Raj8599a412018-11-19 14:51:07 +000054
Derek Lamberti0790dce2019-04-15 18:37:35 +010055 // Check that all inputs are sub-tensors
56 for (auto input : descriptor.m_Inputs)
Nikhil Raj8599a412018-11-19 14:51:07 +000057 {
Derek Lamberti0790dce2019-04-15 18:37:35 +010058 if (!input->GetParent())
59 {
Jim Flynne242f2d2019-05-22 14:24:13 +010060 // Non sub-tensor input found so we need to execute the concat function
Derek Lamberti0790dce2019-04-15 18:37:35 +010061 allInputsAreSubtensors = false;
62 break;
63 }
64 }
65
66 if (allInputsAreSubtensors)
67 {
Jim Flynne242f2d2019-05-22 14:24:13 +010068 // Can skip configuring the concat function since it's not executed
Nikhil Raj8599a412018-11-19 14:51:07 +000069 return;
70 }
71
Teresa Charlin552ee4d2020-07-16 12:44:16 +010072 std::vector<const arm_compute::ITensor *> aclInputs;
Nikhil Raj8599a412018-11-19 14:51:07 +000073 for (auto input : m_Data.m_Inputs)
74 {
Jan Eilers3c9e0452020-04-10 13:00:44 +010075 arm_compute::ITensor& aclInput = armnn::PolymorphicPointerDowncast<IAclTensorHandle>(input)->GetTensor();
Nikhil Raj8599a412018-11-19 14:51:07 +000076 aclInputs.emplace_back(&aclInput);
77 }
Jan Eilers3c9e0452020-04-10 13:00:44 +010078 arm_compute::ITensor& output = armnn::PolymorphicPointerDowncast<IAclTensorHandle>(
Derek Lamberti0790dce2019-04-15 18:37:35 +010079 m_Data.m_Outputs[0])->GetTensor();
Nikhil Raj8599a412018-11-19 14:51:07 +000080
Derek Lamberti0790dce2019-04-15 18:37:35 +010081 // Create the layer function
82 m_Layer.reset(new arm_compute::NEConcatenateLayer());
Nikhil Raj8599a412018-11-19 14:51:07 +000083
Derek Lamberti0790dce2019-04-15 18:37:35 +010084 // Configure input and output tensors
85 size_t aclAxis = CalcAxis(descriptor.m_Parameters);
86 m_Layer->configure(aclInputs, &output, aclAxis);
Nikhil Raj8599a412018-11-19 14:51:07 +000087
Derek Lamberti0790dce2019-04-15 18:37:35 +010088 // Prepare
Matthew Benthamd80a7122019-01-08 17:52:37 +000089 m_Layer->prepare();
Nikhil Raj8599a412018-11-19 14:51:07 +000090}
91
Jim Flynn39d487d2019-05-17 15:44:36 +010092void NeonConcatWorkload::Execute() const
Nikhil Raj8599a412018-11-19 14:51:07 +000093{
Derek Lamberti0790dce2019-04-15 18:37:35 +010094 if (m_Layer)
Nikhil Raj8599a412018-11-19 14:51:07 +000095 {
Jim Flynn39d487d2019-05-17 15:44:36 +010096 ARMNN_SCOPED_PROFILING_EVENT_NEON("NeonConcatWorkload_Execute");
Matthew Benthamd80a7122019-01-08 17:52:37 +000097 m_Layer->run();
Nikhil Raj8599a412018-11-19 14:51:07 +000098 }
99}
100
101} //namespace armnn
102