ArmNN
 25.02
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ClFloorDivWorkload.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2024 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #include "ClFloorDivWorkload.hpp"
8 #include "ClWorkloadUtils.hpp"
11 #include <cl/ClTensorHandle.hpp>
12 
13 using namespace armnn::armcomputetensorutils;
14 
15 namespace armnn
16 {
17 
18 /// Utility function used for the two cast layer inputs to convert the output layer tensor types.
19 inline TensorInfo ConvertTensorToFloat32(const TensorInfo& tensorInfo)
20 {
21  // Change datatype of tensor info and return the new tensor
22  TensorInfo newTensorInfo(tensorInfo);
23  newTensorInfo.SetDataType(DataType::Float32);
24  return newTensorInfo;
25 }
26 
27 /// Utility function used to check if a vector of tensors are Signed32
28 inline bool AreAllTensorsSigned32(const std::vector<TensorInfo>& tensorInfos)
29 {
30  for (const auto& tensorInfo : tensorInfos)
31  {
32  // For every tensorInfo, check the data type, return false if not Signed32
33  if(tensorInfo.GetDataType() != armnn::DataType::Signed32)
34  {
35  return false;
36  }
37  }
38  return true;
39 }
40 
41 /// Utility function used to check if statuses are returning 'OK'
42 inline bool IsValidationPassing(const std::vector<arm_compute::Status>& statuses)
43 {
44  // For each status, check if code is 'OK', if not, return false
45  for (const auto& status : statuses)
46  {
47  if(status.error_code() != arm_compute::ErrorCode::OK)
48  {
49  return false;
50  }
51  }
52  return true;
53 }
54 
56  const TensorInfo& input1Info,
57  const TensorInfo& outputInfo,
58  const ActivationDescriptor* activationDescriptor)
59 {
60  // Transform ArmNN TensorInfo to ACL TensorInfo
61  const arm_compute::TensorInfo inputInfo0 = BuildArmComputeTensorInfo(input0Info);
62  const arm_compute::TensorInfo inputInfo1 = BuildArmComputeTensorInfo(input1Info);
63  const arm_compute::TensorInfo outputInfo0 = BuildArmComputeTensorInfo(outputInfo);
64 
65  const arm_compute::ActivationLayerInfo activationInfo = ConvertActivationDescriptorToAclActivationLayerInfo(
66  activationDescriptor);
67 
68  // If Tensors are Signed32 we need to Cast them to floats, this is to ensure we get the correct
69  // output if the result is a negative number, as we should floor towards -(infinity)
70  if (AreAllTensorsSigned32({input0Info, input1Info, outputInfo}))
71  {
72  // Validate Cast0
73  TensorInfo outputCast0_Info = ConvertTensorToFloat32(input0Info);
74  const arm_compute::TensorInfo outputCast0 = BuildArmComputeTensorInfo(outputCast0_Info);
75 
76  auto statusCast0 = arm_compute::CLCast::validate(&inputInfo0,
77  &outputCast0,
78  arm_compute::ConvertPolicy::WRAP);
79  // Validate Cast1
80  TensorInfo outputCast1_Info = ConvertTensorToFloat32(input1Info);
81  const arm_compute::TensorInfo outputCast1 = BuildArmComputeTensorInfo(outputCast1_Info);
82 
83  auto statusCast1 = arm_compute::CLCast::validate(&inputInfo1,
84  &outputCast1,
85  arm_compute::ConvertPolicy::WRAP);
86 
87  // Validate Div
88  TensorInfo outputDiv_Info = ConvertTensorToFloat32(outputInfo);
89  const arm_compute::TensorInfo outputDivInfo = BuildArmComputeTensorInfo(outputDiv_Info);
90 
91  auto statusDiv = arm_compute::CLArithmeticDivision::validate(&outputCast0,
92  &outputCast1,
93  &outputDivInfo,
94  activationInfo);
95  // Validate Floor
96  TensorInfo outputFloor_Info = ConvertTensorToFloat32(outputInfo);
97  const arm_compute::TensorInfo outputFloorInfo = BuildArmComputeTensorInfo(outputFloor_Info);
98 
99  auto statusFloor = arm_compute::CLFloor::validate(&outputDivInfo,
100  &outputFloorInfo);
101  // Validate Cast2
102  auto statusCast2 = arm_compute::CLCast::validate(&outputFloorInfo,
103  &outputInfo0,
104  arm_compute::ConvertPolicy::WRAP);
105 
106  // Return OK if all the layers are valid
107  if (IsValidationPassing({statusCast0, statusCast1, statusDiv, statusFloor, statusCast2}))
108  {
109  return arm_compute::Status(arm_compute::ErrorCode::OK);
110  }
111  }
112  else
113  {
114  // Validate Div
115  auto statusDiv = arm_compute::CLArithmeticDivision::validate(&inputInfo0,
116  &inputInfo1,
117  &outputInfo0,
118  activationInfo);
119  // Validate Floor
120  auto statusFloor = arm_compute::CLFloor::validate(&outputInfo0,
121  &outputInfo0);
122  // Return OK if all the layers are valid
123  if (IsValidationPassing({statusDiv, statusFloor}))
124  {
125  return arm_compute::Status(arm_compute::ErrorCode::OK);
126  }
127  }
128  return arm_compute::Status(arm_compute::ErrorCode::RUNTIME_ERROR,
129  "ClFloorDivWorkload: FloorDiv layer validation failed.");
130 }
131 
133  const WorkloadInfo& info,
134  const arm_compute::CLCompileContext& clCompileContext)
136 {
137  m_Data.ValidateInputsOutputs("ClFloorDivWorkload", 2, 1);
138 
139  TensorInfo input0Info = info.m_InputTensorInfos[0];
140  TensorInfo input1Info = info.m_InputTensorInfos[1];
141  TensorInfo outputInfo = info.m_OutputTensorInfos[0];
142 
143  arm_compute::ICLTensor& input0 = PolymorphicDowncast<ClTensorHandle*>(m_Data.m_Inputs[0])->GetTensor();
144  arm_compute::ICLTensor& input1 = PolymorphicDowncast<ClTensorHandle*>(m_Data.m_Inputs[1])->GetTensor();
145  arm_compute::ICLTensor& output = PolymorphicDowncast<ClTensorHandle*>(m_Data.m_Outputs[0])->GetTensor();
146 
147  // Get data type of input and output
148  arm_compute::DataType inputDataType = PolymorphicDowncast<ClTensorHandle*>(m_Data.m_Inputs[0])->GetDataType();
149  arm_compute::DataType outputDataType = PolymorphicDowncast<ClTensorHandle*>(m_Data.m_Outputs[0])->GetDataType();
150 
151  const arm_compute::ActivationLayerInfo activationInfo =
153 
154  // If Tensors are Signed32 we need to Cast them to floats, this is to ensure we get the correct
155  // output if the result is a negative number, as we should floor towards -(infinity)
156  if(inputDataType == arm_compute::DataType::S32 && outputDataType == arm_compute::DataType::S32)
157  {
158  // Create new Cast layer pointers if type is S32
159  m_CastLayer0.reset(new arm_compute::CLCast());
160  m_CastLayer1.reset(new arm_compute::CLCast());
161  m_CastLayer2.reset(new arm_compute::CLCast());
162 
163  // Cast Input 0 to type float32
164  TensorInfo outputCast0_Info = ConvertTensorToFloat32(input0Info);
165 
166  // Initialise output tensor based on Float32 type
167  BuildArmComputeTensor(m_OutputCast0, outputCast0_Info);
168  armcomputetensorutils::InitialiseArmComputeTensorEmpty(m_OutputCast0);
169 
170  // Configure first Cast Layer
171  m_CastLayer0->configure(clCompileContext, &input0, &m_OutputCast0, arm_compute::ConvertPolicy::WRAP);
172 
173  // Cast Input 1 to type Float32
174  TensorInfo outputCast1_Info = ConvertTensorToFloat32(input1Info);
175 
176  // Initialise Output tensor based on Float32 type
177  BuildArmComputeTensor(m_OutputCast1, outputCast1_Info);
178  armcomputetensorutils::InitialiseArmComputeTensorEmpty(m_OutputCast1);
179 
180  // Configure second Cast Layer
181  m_CastLayer1->configure(clCompileContext, &input1, &m_OutputCast1, arm_compute::ConvertPolicy::WRAP);
182 
183  // Create Div output tensor
184  TensorInfo outputDiv_Info = ConvertTensorToFloat32(outputInfo);
185  BuildArmComputeTensor(m_OutputDiv, outputDiv_Info);
186  armcomputetensorutils::InitialiseArmComputeTensorEmpty(m_OutputDiv);
187 
188  // Configure Div Layer
189  m_DivLayer.configure(clCompileContext, &m_OutputCast0, &m_OutputCast1, &m_OutputDiv, activationInfo);
190 
191  // Create Floor output tensor
192  BuildArmComputeTensor(m_OutputFloor, outputDiv_Info);
193  armcomputetensorutils::InitialiseArmComputeTensorEmpty(m_OutputFloor);
194 
195  // Configure Floor Layer
196  m_FloorLayer.configure(clCompileContext, &m_OutputDiv, &m_OutputFloor);
197 
198  // Configure third Cast Layer
199  m_CastLayer2->configure(clCompileContext, &m_OutputFloor, &output, arm_compute::ConvertPolicy::WRAP);
200  }
201  else
202  {
203  // Create Div output tensor
204  BuildArmComputeTensor(m_OutputDiv, outputInfo);
205  armcomputetensorutils::InitialiseArmComputeTensorEmpty(m_OutputDiv);
206 
207  // Configure Div Layer
208  m_DivLayer.configure(clCompileContext, &input0, &input1, &m_OutputDiv, activationInfo);
209 
210  // Configure Floor Layer
211  m_FloorLayer.configure(clCompileContext, &m_OutputDiv, &output);
212  }
213 };
214 
216 {
217  ARMNN_SCOPED_PROFILING_EVENT_CL_NAME_GUID("ClFloorDivWorkload_Execute");
218  // Only run Cast Layers if needed. e.g. if it exists
219  if(m_CastLayer0 && m_CastLayer1)
220  {
221  m_CastLayer0->run();
222  m_CastLayer1->run();
223 
224  // Delete objects after running layer
225  m_CastLayer0.reset();
226  m_CastLayer1.reset();
227  }
228  RunClFunction(m_DivLayer, CHECK_LOCATION());
229  RunClFunction(m_FloorLayer, CHECK_LOCATION());
230  if(m_CastLayer2)
231  {
232  m_CastLayer2->run();
233 
234  // Delete object after running layer
235  m_CastLayer2.reset();
236  }
237 }
238 } // namespace armnn
#define ARMNN_SCOPED_PROFILING_EVENT_CL_NAME_GUID(label)
Creates a profiling event that uses GetGuid() and GetName() from the calling class.
#define CHECK_LOCATION()
Definition: Exceptions.hpp:203
QueueDescriptor m_Data
Definition: Workload.hpp:74
ClFloorDivWorkload(const DivisionQueueDescriptor &descriptor, const WorkloadInfo &info, const arm_compute::CLCompileContext &clCompileContext)
virtual void Execute() const override
void SetDataType(DataType type)
Definition: Tensor.hpp:201
Copyright (c) 2021 ARM Limited and Contributors.
Status
enumeration
Definition: Types.hpp:43
bool AreAllTensorsSigned32(const std::vector< TensorInfo > &tensorInfos)
Utility function used to check if a vector of tensors are Signed32.
bool IsValidationPassing(const std::vector< arm_compute::Status > &statuses)
Utility function used to check if statuses are returning 'OK'.
arm_compute::Status ClFloorDivWorkloadValidate(const TensorInfo &input0Info, const TensorInfo &input1Info, const TensorInfo &outputInfo, const ActivationDescriptor *activationDescriptor)
arm_compute::ActivationLayerInfo ConvertAdditionalInfoToAclActivationLayerInfo(const QueueDescriptor &queueDescriptor)
arm_compute::ActivationLayerInfo ConvertActivationDescriptorToAclActivationLayerInfo(const ActivationDescriptor &actDesc)
DataType
Definition: Types.hpp:49
TensorInfo ConvertTensorToFloat32(const TensorInfo &tensorInfo)
Utility function used for the two cast layer inputs to convert the output layer tensor types.
void RunClFunction(arm_compute::IFunction &function, const CheckLocation &location)
An ActivationDescriptor for the ActivationLayer.
Definition: Descriptors.hpp:37
std::vector< ITensorHandle * > m_Inputs
std::vector< ITensorHandle * > m_Outputs
void ValidateInputsOutputs(const std::string &descName, unsigned int numExpectedIn, unsigned int numExpectedOut) const
Contains information about TensorInfos of a layer.