blob: 5b5614662dd22143e47fbd10592fa101e9b886f5 [file] [log] [blame]
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#include "NeonSplitterWorkload.hpp"
7
8#include "NeonWorkloadUtils.hpp"
9
10#include <aclCommon/ArmComputeTensorUtils.hpp>
11#include <aclCommon/ArmComputeUtils.hpp>
12#include <backendsCommon/CpuTensorHandle.hpp>
13#include <neon/NeonTensorHandle.hpp>
14
15
16namespace armnn
17{
18
19using namespace armcomputetensorutils;
20
21namespace
22{
23unsigned int CalcAclAxis(unsigned int numDimensions, unsigned int splitAxis)
24{
25 return (numDimensions - splitAxis) - 1;
26}
27
28} //namespace
29
30arm_compute::Status NeonSplitterWorkloadValidate(const TensorInfo& input,
31 const std::vector<std::reference_wrapper<TensorInfo>>& outputs,
32 unsigned int splitAxis)
33{
34 const arm_compute::TensorInfo aclInputInfo = BuildArmComputeTensorInfo(input);
35
36 size_t numOutputs = outputs.size();
37
38 std::vector<arm_compute::TensorInfo> aclOutputs;
39 aclOutputs.reserve(numOutputs);
40
41 std::vector<arm_compute::ITensorInfo*> aclOutputPtr;
42 aclOutputPtr.reserve(numOutputs);
43
44 for (size_t i = 0u; i < outputs.size(); ++i)
45 {
46 aclOutputs.emplace_back(BuildArmComputeTensorInfo(outputs[i]));
47 aclOutputPtr.emplace_back(&aclOutputs.back());
48 }
49
50 unsigned int aclAxis = CalcAclAxis(input.GetNumDimensions(), splitAxis);
51 return arm_compute::NESplit::validate(&aclInputInfo, aclOutputPtr, aclAxis);
52}
53
54NeonSplitterWorkload::NeonSplitterWorkload(const SplitterQueueDescriptor& descriptor, const WorkloadInfo& info)
55 : BaseWorkload<SplitterQueueDescriptor>(descriptor, info)
56{
57 bool allOutputsAreSubtensors = true;
58
59 // Check that all outputs are sub-tensors
60 for (auto output : m_Data.m_Outputs)
61 {
62 if (output && !output->GetParent())
63 {
64 // Non sub-tensor input found so we need to execute the split function
65 allOutputsAreSubtensors = false;
66 break;
67 }
68 }
69
70 if (allOutputsAreSubtensors)
71 {
72 // Can skip configuring the split function since it's not executed
73 return;
74 }
75
Derek Lambertic81855f2019-06-13 17:34:19 +010076 arm_compute::ITensor& input = boost::polymorphic_downcast<IAclTensorHandle*>(m_Data.m_Inputs[0])->GetTensor();
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +010077
78 std::vector<arm_compute::ITensor *> aclOutputs;
79 for (auto output : m_Data.m_Outputs)
80 {
Derek Lambertic81855f2019-06-13 17:34:19 +010081 arm_compute::ITensor& aclOutput = boost::polymorphic_pointer_downcast<IAclTensorHandle>(output)->GetTensor();
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +010082 aclOutputs.emplace_back(&aclOutput);
83 }
84
85 // Create the layer function
86 m_Layer.reset(new arm_compute::NESplit());
87
88 // Configure input and output tensors
89 std::set<unsigned int> splitAxis = ComputeSplitAxis(descriptor.m_Parameters, m_Data.m_Inputs[0]->GetShape());
90 if (splitAxis.size() != 1)
91 {
92 throw InvalidArgumentException("Cannot derive split axis from SplitterDescriptor");
93 }
94
95 unsigned int aclAxis = CalcAclAxis(descriptor.m_Parameters.GetNumDimensions(), *splitAxis.begin());
96 m_Layer->configure(&input, aclOutputs, aclAxis);
97
98 // Prepare
99 m_Layer->prepare();
100}
101
102void NeonSplitterWorkload::Execute() const
103{
104 if (m_Layer)
105 {
106 ARMNN_SCOPED_PROFILING_EVENT_NEON("NeonSplitterWorkload_Execute");
107 m_Layer->run();
108 }
109}
110
111} //namespace armnn
112