blob: 9bbbcab797db8c29d50407247ba395bc3e22ea19 [file] [log] [blame]
Narumol Prangnawarat74135832019-05-23 15:07:33 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#include "ClSplitterWorkload.hpp"
7
8#include "ClWorkloadUtils.hpp"
9
10#include <aclCommon/ArmComputeTensorUtils.hpp>
11#include <aclCommon/ArmComputeUtils.hpp>
12#include <backendsCommon/CpuTensorHandle.hpp>
13#include <cl/ClTensorHandle.hpp>
14
15
16namespace armnn
17{
18
19using namespace armcomputetensorutils;
20
21namespace
22{
23 unsigned int CalcAclAxis(unsigned int numDimensions, unsigned int splitAxis)
24 {
25 return (numDimensions - splitAxis) - 1;
26 }
27
28} //namespace
29
30arm_compute::Status ClSplitterWorkloadValidate(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::CLSplit::validate(&aclInputInfo, aclOutputPtr, aclAxis);
52}
53
54ClSplitterWorkload::ClSplitterWorkload(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
76 arm_compute::ICLTensor& input = boost::polymorphic_pointer_downcast<IClTensorHandle>(
77 m_Data.m_Inputs[0])->GetTensor();
78
79 std::vector<arm_compute::ICLTensor *> aclOutputs;
80 for (auto output : m_Data.m_Outputs)
81 {
82 arm_compute::ICLTensor& aclOutput = boost::polymorphic_pointer_downcast<IClTensorHandle>(output)->GetTensor();
83 aclOutputs.emplace_back(&aclOutput);
84 }
85
86 // Create the layer function
87 m_Layer.reset(new arm_compute::CLSplit());
88
89 // Configure input and output tensors
90 std::set<unsigned int> splitAxis = ComputeSplitAxis(descriptor.m_Parameters, m_Data.m_Inputs[0]->GetShape());
91 if (splitAxis.size() != 1)
92 {
93 throw InvalidArgumentException("Cannot derive split axis from SplitterDescriptor");
94 }
95
96 unsigned int aclAxis = CalcAclAxis(descriptor.m_Parameters.GetNumDimensions(), *splitAxis.begin());
97 m_Layer->configure(&input, aclOutputs, aclAxis);
98
99 // Prepare
100 m_Layer->prepare();
101}
102
103void ClSplitterWorkload::Execute() const
104{
105 if (m_Layer)
106 {
107 ARMNN_SCOPED_PROFILING_EVENT_CL("ClSplitterWorkload_Execute");
108 m_Layer->run();
109 }
110}
111
112} //namespace armnn