xref: /aosp_15_r20/external/armnn/src/backends/neon/workloads/NeonBatchNormalizationWorkload.cpp (revision 89c4ff92f2867872bb9e2354d150bf0c8c502810)
1 //
2 // Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #include "NeonBatchNormalizationWorkload.hpp"
7 
8 #include "NeonWorkloadUtils.hpp"
9 
10 #include <aclCommon/ArmComputeTensorUtils.hpp>
11 #include <aclCommon/ArmComputeUtils.hpp>
12 
13 #include <armnn/utility/PolymorphicDowncast.hpp>
14 
15 #include <armnn/backends/TensorHandle.hpp>
16 
17 #include <arm_compute/runtime/NEON/functions/NEBatchNormalizationLayer.h>
18 
19 namespace armnn
20 {
21 using namespace armcomputetensorutils;
22 
23 
NeonBatchNormalizationValidate(const TensorInfo & input,const TensorInfo & output,const TensorInfo & mean,const TensorInfo & var,const TensorInfo & beta,const TensorInfo & gamma,const BatchNormalizationDescriptor & descriptor,const ActivationDescriptor * activationDescriptor)24 arm_compute::Status NeonBatchNormalizationValidate(const TensorInfo& input,
25                                                    const TensorInfo& output,
26                                                    const TensorInfo& mean,
27                                                    const TensorInfo& var,
28                                                    const TensorInfo& beta,
29                                                    const TensorInfo& gamma,
30                                                    const BatchNormalizationDescriptor& descriptor,
31                                                    const ActivationDescriptor* activationDescriptor)
32 {
33     const arm_compute::TensorInfo aclInputInfo =
34           armcomputetensorutils::BuildArmComputeTensorInfo(input, descriptor.m_DataLayout);
35     const arm_compute::TensorInfo aclOutputInfo =
36           armcomputetensorutils::BuildArmComputeTensorInfo(output, descriptor.m_DataLayout);
37     const arm_compute::TensorInfo aclMeanInfo =
38           armcomputetensorutils::BuildArmComputeTensorInfo(mean, descriptor.m_DataLayout);
39     const arm_compute::TensorInfo aclVarInfo =
40           armcomputetensorutils::BuildArmComputeTensorInfo(var, descriptor.m_DataLayout);
41     const arm_compute::TensorInfo aclBetaInfo =
42           armcomputetensorutils::BuildArmComputeTensorInfo(beta, descriptor.m_DataLayout);
43     const arm_compute::TensorInfo aclGammaInfo =
44           armcomputetensorutils::BuildArmComputeTensorInfo(gamma, descriptor.m_DataLayout);
45 
46     const arm_compute::ActivationLayerInfo activationInfo = ConvertActivationDescriptorToAclActivationLayerInfo(
47             activationDescriptor);
48 
49     return arm_compute::NEBatchNormalizationLayer::validate(&aclInputInfo,
50                                                             &aclOutputInfo,
51                                                             &aclMeanInfo,
52                                                             &aclVarInfo,
53                                                             &aclBetaInfo,
54                                                             &aclGammaInfo,
55                                                             descriptor.m_Eps,
56                                                             activationInfo);
57 }
58 
NeonBatchNormalizationWorkload(const BatchNormalizationQueueDescriptor & descriptor,const WorkloadInfo & info)59 NeonBatchNormalizationWorkload::NeonBatchNormalizationWorkload(
60     const BatchNormalizationQueueDescriptor& descriptor, const WorkloadInfo& info)
61     : NeonBaseWorkload<BatchNormalizationQueueDescriptor>(descriptor, info)
62 {
63     // Report Profiling Details
64     ARMNN_REPORT_PROFILING_WORKLOAD_DESC("NeonBatchNormalizationWorkload_Construct",
65                                          descriptor.m_Parameters,
66                                          info,
67                                          this->GetGuid());
68 
69     m_Data.ValidateInputsOutputs("NeonBatchNormalizationWorkload", 1, 1);
70 
71     arm_compute::ITensor& input = PolymorphicDowncast<IAclTensorHandle*>(m_Data.m_Inputs[0])->GetTensor();
72     arm_compute::ITensor& output = PolymorphicDowncast<IAclTensorHandle*>(m_Data.m_Outputs[0])->GetTensor();
73 
74     arm_compute::DataLayout aclDataLayout = ConvertDataLayout(m_Data.m_Parameters.m_DataLayout);
75     input.info()->set_data_layout(aclDataLayout);
76     output.info()->set_data_layout(aclDataLayout);
77 
78     m_Mean = std::make_unique<arm_compute::Tensor>();
79     BuildArmComputeTensor(*m_Mean, m_Data.m_Mean->GetTensorInfo());
80 
81     m_Variance = std::make_unique<arm_compute::Tensor>();
82     BuildArmComputeTensor(*m_Variance, m_Data.m_Variance->GetTensorInfo());
83 
84     m_Gamma = std::make_unique<arm_compute::Tensor>();
85     BuildArmComputeTensor(*m_Gamma, m_Data.m_Gamma->GetTensorInfo());
86 
87     m_Beta = std::make_unique<arm_compute::Tensor>();
88     BuildArmComputeTensor(*m_Beta, m_Data.m_Beta->GetTensorInfo());
89 
90     const arm_compute::ActivationLayerInfo activationInfo = ConvertAdditionalInfoToAclActivationLayerInfo(descriptor);
91 
92     auto layer = std::make_unique<arm_compute::NEBatchNormalizationLayer>();
93     layer->configure(&input,
94                      &output,
95                      m_Mean.get(),
96                      m_Variance.get(),
97                      m_Beta.get(),
98                      m_Gamma.get(),
99                      m_Data.m_Parameters.m_Eps,
100                      activationInfo);
101     m_Layer.reset(layer.release());
102 
103     InitializeArmComputeTensorData(*m_Mean, m_Data.m_Mean);
104     InitializeArmComputeTensorData(*m_Variance, m_Data.m_Variance);
105     InitializeArmComputeTensorData(*m_Gamma, m_Data.m_Gamma);
106     InitializeArmComputeTensorData(*m_Beta, m_Data.m_Beta);
107 
108     // Force Compute Library to perform the necessary copying and reshaping, after which
109     // delete all the input tensors that will no longer be needed
110     m_Layer->prepare();
111     FreeUnusedTensors();
112 }
113 
Execute() const114 void NeonBatchNormalizationWorkload::Execute() const
115 {
116     ARMNN_SCOPED_PROFILING_EVENT_NEON_GUID("NeonBatchNormalizationWorkload_Execute", this->GetGuid());
117     m_Layer->run();
118 }
119 
FreeUnusedTensors()120 void NeonBatchNormalizationWorkload::FreeUnusedTensors()
121 {
122     FreeTensorIfUnused(m_Mean);
123     FreeTensorIfUnused(m_Variance);
124     FreeTensorIfUnused(m_Gamma);
125     FreeTensorIfUnused(m_Beta);
126 }
127 
128 } //namespace armnn
129