• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 #include "ClConcatWorkload.hpp"
6 #include "ClWorkloadUtils.hpp"
7 #include <aclCommon/ArmComputeTensorUtils.hpp>
8 #include <armnn/utility/PolymorphicDowncast.hpp>
9 #include <backendsCommon/CpuTensorHandle.hpp>
10 #include <cl/ClTensorHandle.hpp>
11 #include <cl/ClLayerSupport.hpp>
12 
13 #include <arm_compute/core/Types.h>
14 #include <arm_compute/runtime/CL/functions/CLConcatenateLayer.h>
15 
16 namespace armnn
17 {
18 using namespace armcomputetensorutils;
19 
20 namespace
21 {
CalcAxis(const OriginsDescriptor & desc)22 size_t CalcAxis(const OriginsDescriptor& desc)
23 {
24     return (desc.GetNumDimensions() - desc.GetConcatAxis()) - 1;
25 }
26 } //namespace
27 
ClConcatWorkloadValidate(const std::vector<const TensorInfo * > & inputs,const TensorInfo & output,const OriginsDescriptor & descriptor)28 arm_compute::Status ClConcatWorkloadValidate(const std::vector<const TensorInfo*>& inputs,
29                                              const TensorInfo& output,
30                                              const OriginsDescriptor& descriptor)
31 {
32     std::vector<arm_compute::TensorInfo> aclInputs;
33     for (const TensorInfo* input : inputs)
34     {
35         arm_compute::TensorInfo aclInputInfo = BuildArmComputeTensorInfo(*input, armnn::DataLayout::NCHW);
36         aclInputs.emplace_back(aclInputInfo);
37     }
38     const arm_compute::TensorInfo aclOutputInfo = BuildArmComputeTensorInfo(output);
39     std::vector<const arm_compute::ITensorInfo*> aclInputPtrs;
40     for (arm_compute::ITensorInfo& input : aclInputs)
41     {
42         aclInputPtrs.emplace_back(&input);
43     }
44 
45     size_t aclAxis = CalcAxis(descriptor);
46     return arm_compute::CLConcatenateLayer::validate(aclInputPtrs, &aclOutputInfo, aclAxis);
47 }
48 
ClConcatWorkload(const ConcatQueueDescriptor & descriptor,const WorkloadInfo & info)49 ClConcatWorkload::ClConcatWorkload(const ConcatQueueDescriptor& descriptor, const WorkloadInfo& info)
50 : BaseWorkload<ConcatQueueDescriptor>(descriptor, info)
51 {
52     bool allInputsAreSubtensors = true;
53 
54     // Check that all inputs are sub-tensors
55     for (auto input : descriptor.m_Inputs)
56     {
57         if (!input->GetParent())
58         {
59             // Non sub-tensor input found so we need to execute the concat function
60             allInputsAreSubtensors = false;
61             break;
62         }
63     }
64 
65     if (allInputsAreSubtensors)
66     {
67         // Can skip configuring the concat function since it's not executed
68         return;
69     }
70 
71     std::vector<const arm_compute::ICLTensor *> aclInputs;
72     for (auto input : m_Data.m_Inputs)
73     {
74         arm_compute::ICLTensor& aclInput  = armnn::PolymorphicPointerDowncast<IClTensorHandle>(input)->GetTensor();
75         aclInputs.emplace_back(&aclInput);
76     }
77 
78     arm_compute::ICLTensor& output =
79             armnn::PolymorphicPointerDowncast<IClTensorHandle>(m_Data.m_Outputs[0])->GetTensor();
80 
81     // Create the layer function
82     auto layer = std::make_unique<arm_compute::CLConcatenateLayer>();
83 
84     // Configure input and output tensors
85     size_t aclAxis = CalcAxis(descriptor.m_Parameters);
86     layer->configure(aclInputs, &output, aclAxis);
87 
88     // Prepare
89     layer->prepare();
90     m_Layer = std::move(layer);
91 }
92 
Execute() const93 void ClConcatWorkload::Execute() const
94 {
95     if (m_Layer)
96     {
97         ARMNN_SCOPED_PROFILING_EVENT_CL("ClConcatWorkload_Execute");
98         m_Layer->run();
99     }
100 }
101 
102 } //namespace armnn
103