ArmNN
 25.11
Loading...
Searching...
No Matches
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
8#include "ClWorkloadUtils.hpp"
11#include <cl/ClTensorHandle.hpp>
12
13using namespace armnn::armcomputetensorutils;
14
15namespace armnn
16{
17
18/// Utility function used for the two cast layer inputs to convert the output layer tensor types.
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
28inline 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'
42inline 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
55arm_compute::Status ClFloorDivWorkloadValidate(const TensorInfo& input0Info,
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()
ClBaseWorkload(const DivisionQueueDescriptor &descriptor, const WorkloadInfo &info)
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.
bool AreAllTensorsSigned32(const std::vector< TensorInfo > &tensorInfos)
Utility function used to check if a vector of tensors are Signed32.
void RunClFunction(arm_compute::IFunction &function, const CheckLocation &location)
arm_compute::ActivationLayerInfo ConvertAdditionalInfoToAclActivationLayerInfo(const QueueDescriptor &queueDescriptor)
bool IsValidationPassing(const std::vector< arm_compute::Status > &statuses)
Utility function used to check if statuses are returning 'OK'.
DestType PolymorphicDowncast(SourceType *value)
Polymorphic downcast for build in pointers only.
arm_compute::Status ClFloorDivWorkloadValidate(const TensorInfo &input0Info, const TensorInfo &input1Info, const TensorInfo &outputInfo, const ActivationDescriptor *activationDescriptor)
arm_compute::ActivationLayerInfo ConvertActivationDescriptorToAclActivationLayerInfo(const ActivationDescriptor &actDesc)
TensorInfo ConvertTensorToFloat32(const TensorInfo &tensorInfo)
Utility function used for the two cast layer inputs to convert the output layer tensor types.
An ActivationDescriptor for the ActivationLayer.
Contains information about TensorInfos of a layer.