xref: /aosp_15_r20/external/ComputeLibrary/src/dynamic_fusion/sketch/gpu/operators/GpuPool2d.cpp (revision c217d954acce2dbc11938adb493fc0abd69584f3)
1 /*
2  * Copyright (c) 2023 Arm Limited.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 
25 #include "arm_compute/core/CL/CLCompileContext.h"
26 #include "arm_compute/core/Validate.h"
27 #include "arm_compute/core/experimental/Types.h"
28 #include "arm_compute/core/utils/misc/ShapeCalculator.h"
29 #include "arm_compute/dynamic_fusion/sketch/gpu/GpuWorkloadContext.h"
30 
31 #include "arm_compute/dynamic_fusion/sketch/gpu/GpuWorkloadSketch.h"
32 #include "arm_compute/dynamic_fusion/sketch/gpu/operators/GpuPool2d.h"
33 #include "src/common/utils/Log.h"
34 #include "src/core/helpers/AutoConfiguration.h"
35 #include "src/dynamic_fusion/sketch/ArgumentPack.h"
36 #include "src/dynamic_fusion/sketch/gpu/GpuWorkloadSketchImpl.h"
37 #include "src/dynamic_fusion/sketch/gpu/GpuWorkloadSourceCode.h"
38 #include "src/dynamic_fusion/sketch/gpu/components/cl/ClComponentPool2d.h"
39 #include "src/dynamic_fusion/utils/Utils.h"
40 
41 namespace arm_compute
42 {
43 namespace experimental
44 {
45 namespace dynamic_fusion
46 {
47 namespace
48 {
49 constexpr GpuOperatorType operator_type = GpuOperatorType::Unfusable;
50 } // namespace
51 
mixed_precision(bool mixed_precision)52 GpuPool2dSettings &GpuPool2dSettings::mixed_precision(bool mixed_precision)
53 {
54     _mixed_precision = mixed_precision;
55     return *this;
56 }
57 
mixed_precision() const58 bool GpuPool2dSettings::mixed_precision() const
59 {
60     return _mixed_precision;
61 }
62 
validate_op(const GpuWorkloadSketch & sketch,const ITensorInfo * src,const ITensorInfo * dst,const Pool2dAttributes & attributes,const GpuPool2dSettings & settings)63 Status GpuPool2d::validate_op(const GpuWorkloadSketch &sketch,
64                               const ITensorInfo       *src,
65                               const ITensorInfo       *dst,
66                               const Pool2dAttributes &attributes,
67                               const GpuPool2dSettings &settings)
68 {
69     ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(src, dst);
70     ARM_COMPUTE_RETURN_ERROR_ON(!src->has_valid_id() || !dst->has_valid_id());
71 
72     // Auto initialize dst tensor info
73     TensorInfo dst_info_to_validate = *dst;
74     {
75         auto shape = misc::shape_calculator::compute_pool_shape(*src, convert_pool_attr_to_pool_info(attributes, settings.mixed_precision()));
76         auto_init_if_empty(dst_info_to_validate, src->clone()->set_tensor_shape(shape));
77     }
78 
79     // Perform fusion test
80     // Pack tensor infos
81     ArgumentPack<ITensorInfo> tensors;
82     tensors.add_const_tensor(ACL_SRC_0, src);
83     tensors.add_const_tensor(ACL_DST_0, &dst_info_to_validate);
84 
85     const auto op = sketch.implementation().operator_group().new_operator(operator_type, tensors);
86     ARM_COMPUTE_RETURN_ERROR_ON_MSG(!sketch.implementation().operator_group().try_add_operator(op),
87                                     "Operator fusion test failed. This operator cannot be fused into the workload");
88 
89     // Check if configuration is supported
90     return is_supported_op(*sketch.gpu_context(), src, &dst_info_to_validate, attributes, settings);
91 }
92 
is_supported_op(const GpuWorkloadContext & context,const ITensorInfo * src,const ITensorInfo * dst,const Pool2dAttributes & attributes,const GpuPool2dSettings & settings)93 Status GpuPool2d::is_supported_op(const GpuWorkloadContext &context,
94                                   const ITensorInfo        *src,
95                                   const ITensorInfo        *dst,
96                                   const Pool2dAttributes   &attributes,
97                                   const GpuPool2dSettings &settings)
98 {
99     ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(src, dst);
100     // Data type
101     ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(src, 1, DataType::F16, DataType::F32);
102     // Data layout
103     ARM_COMPUTE_RETURN_ERROR_ON_DATA_LAYOUT_NOT_IN(src, DataLayout::NHWC);
104     // Check exclude padding is not false
105     ARM_COMPUTE_RETURN_ERROR_ON_MSG(!attributes.exclude_padding(), "Exclude padding must be set to true in Attributes!");
106 
107     // Auto initialize dst tensor info
108     TensorInfo dst_info_to_validate = *dst;
109     {
110         auto shape = misc::shape_calculator::compute_pool_shape(*src, convert_pool_attr_to_pool_info(attributes, settings.mixed_precision()));
111         auto_init_if_empty(dst_info_to_validate, src->clone()->set_tensor_shape(shape));
112     }
113 
114     // Check components
115     if(context.gpu_language() == GpuLanguage::OpenCL)
116     {
117         const auto cl_compile_ctx = context.cl_compile_context();
118         ARM_COMPUTE_RETURN_ERROR_ON(cl_compile_ctx == nullptr);
119 
120         // Validate Component
121         {
122             const KernelProperties properties = IGpuKernelComponent::Properties().stage(UnitWorkloadStage{ UnitWorkloadStage::Stage::Run });
123 
124             ArgumentPack<ITensorInfo> arguments;
125             arguments.add_const_tensor(ACL_SRC_0, src);
126             arguments.add_const_tensor(ACL_DST_0, &dst_info_to_validate);
127             ARM_COMPUTE_RETURN_ON_ERROR(ClComponentPool2d::validate(properties, arguments, attributes, settings));
128         }
129     }
130     else
131     {
132         ARM_COMPUTE_RETURN_ERROR_MSG("Unimplemented Gpu language");
133     }
134     return Status{};
135 }
136 
create_op(GpuWorkloadSketch & sketch,ITensorInfo * src,ITensorInfo * dst,const Pool2dAttributes & attributes,const GpuPool2dSettings & settings)137 void GpuPool2d::create_op(GpuWorkloadSketch       &sketch,
138                           ITensorInfo             *src,
139                           ITensorInfo             *dst,
140                           const Pool2dAttributes &attributes,
141                           const GpuPool2dSettings &settings)
142 {
143     // Assert validation
144     ARM_COMPUTE_ERROR_THROW_ON(GpuPool2d::validate_op(sketch, src, dst, attributes, settings));
145     ARM_COMPUTE_LOG_PARAMS(src, dst, attributes, settings);
146 
147     // Auto initialize dst tensor
148     {
149         auto shape = misc::shape_calculator::compute_pool_shape(*src, convert_pool_attr_to_pool_info(attributes, settings.mixed_precision())); // use the default DimensionRoundingType
150         auto_init_if_empty(*dst, src->clone()->set_tensor_shape(shape));
151     }
152 
153     // Translate into components and add to component graph
154     auto &comp_graph = sketch.implementation().component_graph();
155 
156     const auto sketch_ctx = sketch.implementation().context();
157 
158     if(sketch_ctx->gpu_language() == GpuLanguage::OpenCL)
159     {
160         const auto cl_compile_ctx = sketch_ctx->cl_compile_context();
161         ARM_COMPUTE_ERROR_ON(cl_compile_ctx == nullptr);
162 
163         // Add Component
164         {
165             auto properties = IGpuKernelComponent::Properties();
166             properties.stage(UnitWorkloadStage{ UnitWorkloadStage::Stage::Run });
167 
168             ArgumentPack<ITensorInfo> arguments;
169             arguments.add_const_tensor(ACL_SRC_0, src);
170             arguments.add_const_tensor(ACL_DST_0, dst);
171             comp_graph.add_new_component<ClComponentPool2d>(properties, arguments, attributes, settings);
172         }
173     }
174     else
175     {
176         ARM_COMPUTE_ERROR("Unimplemented Gpu language");
177     }
178 
179     // Set up fusion test by adding to the Operator Group
180     // Note this has to be performed after all the components have been successfully added to the component graph
181 
182     // Pack tensor infos
183     ArgumentPack<ITensorInfo> tensors;
184     tensors.add_const_tensor(ACL_SRC_0, src);
185     tensors.add_tensor(ACL_DST_0, dst);
186 
187     const auto op = sketch.implementation().operator_group().new_operator(operator_type, tensors);
188     sketch.implementation().operator_group().add_operator(op);
189 }
190 
191 } // namespace dynamic_fusion
192 } // namespace experimental
193 } // namespace arm_compute
194