xref: /aosp_15_r20/external/ComputeLibrary/src/dynamic_fusion/sketch/gpu/operators/GpuResize.cpp (revision c217d954acce2dbc11938adb493fc0abd69584f3)
1 /*
2  * Copyright (c) 2022-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/dynamic_fusion/sketch/gpu/operators/GpuResize.h"
26 
27 #include "arm_compute/core/Error.h"
28 #include "arm_compute/core/utils/misc/ShapeCalculator.h"
29 #include "src/core/helpers/AutoConfiguration.h"
30 #include "src/dynamic_fusion/sketch/ArgumentPack.h"
31 #include "src/dynamic_fusion/sketch/gpu/GpuWorkloadSketchImpl.h"
32 #include "src/dynamic_fusion/sketch/gpu/components/cl/ClComponentResize.h"
33 
34 #include "src/common/utils/Log.h"
35 
36 namespace arm_compute
37 {
38 namespace experimental
39 {
40 namespace dynamic_fusion
41 {
42 namespace
43 {
calculate_and_init_dst_if_empty(ITensorInfo * dst,const ITensorInfo * src,const ResizeAttributes & attributes)44 void calculate_and_init_dst_if_empty(ITensorInfo *dst, const ITensorInfo *src, const ResizeAttributes &attributes)
45 {
46     if(dst->total_size() == 0U)
47     {
48         TensorShape out_shape = src->tensor_shape();
49 
50         out_shape.set(1, attributes.output_width());
51         out_shape.set(2, attributes.output_height());
52 
53         auto_init_if_empty(*dst, src->clone()->set_tensor_shape(out_shape));
54     }
55 }
56 
is_supported_op_helper(const GpuWorkloadContext & context,const ITensorInfo * src,const ITensorInfo * dst,const ResizeAttributes & attributes)57 Status is_supported_op_helper(const GpuWorkloadContext &context,
58                               const ITensorInfo        *src,
59                               const ITensorInfo        *dst,
60                               const ResizeAttributes   &attributes)
61 {
62     ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(src);
63 
64     TensorInfo         dst_info_to_validate;
65     const ITensorInfo *dst_info_to_validate_ptr = &dst_info_to_validate;
66 
67     if(dst != nullptr)
68     {
69         dst_info_to_validate_ptr = dst;
70     }
71 
72     calculate_and_init_dst_if_empty(&dst_info_to_validate, src, attributes);
73 
74     // Check support level
75     // Data type
76     ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(src, 1, DataType::QASYMM8, DataType::QASYMM8_SIGNED, DataType::U8, DataType::S16, DataType::F16, DataType::F32);
77     // Data layout
78     ARM_COMPUTE_RETURN_ERROR_ON_DATA_LAYOUT_NOT_IN(src, DataLayout::NHWC);
79     // Interpolation policy
80     ARM_COMPUTE_RETURN_ERROR_ON_MSG(attributes.interpolation_policy() != InterpolationPolicy::NEAREST_NEIGHBOR && attributes.interpolation_policy() != InterpolationPolicy::BILINEAR,
81                                     "Interpolation policy must be NEAREST_NEIGHBOR or BILINEAR");
82 
83     // Check components
84     if(context.gpu_language() == GpuLanguage::OpenCL)
85     {
86         const auto cl_compile_ctx = context.cl_compile_context();
87         ARM_COMPUTE_RETURN_ERROR_ON(cl_compile_ctx == nullptr);
88 
89         // Validate Activation Component
90         {
91             const KernelProperties properties = IGpuKernelComponent::Properties().stage(UnitWorkloadStage{ UnitWorkloadStage::Stage::Run });
92 
93             ArgumentPack<ITensorInfo> arguments;
94             arguments.add_const_tensor(ACL_SRC_0, src);
95             arguments.add_const_tensor(ACL_DST_0, dst_info_to_validate_ptr);
96             ARM_COMPUTE_RETURN_ON_ERROR(ClComponentResize::validate(properties, arguments, attributes));
97         }
98     }
99     else
100     {
101         ARM_COMPUTE_RETURN_ERROR_MSG("Unimplemented Gpu language");
102     }
103 
104     return Status{};
105 }
106 
107 constexpr GpuOperatorType operator_type = GpuOperatorType::Complex;
108 } // namespace
109 
is_supported_op(const GpuWorkloadContext & context,const ITensorInfo * src,const Attributes & attributes)110 Status GpuResize::is_supported_op(const GpuWorkloadContext &context,
111                                   const ITensorInfo        *src,
112                                   const Attributes         &attributes)
113 {
114     return is_supported_op_helper(context, src, nullptr, attributes);
115 }
116 
validate_op(const GpuWorkloadSketch & sketch,const ITensorInfo * src,const GpuResize::Attributes & attributes)117 Status GpuResize::validate_op(const GpuWorkloadSketch     &sketch,
118                               const ITensorInfo           *src,
119                               const GpuResize::Attributes &attributes)
120 {
121     ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(src);
122     ARM_COMPUTE_RETURN_ERROR_ON(!src->has_valid_id());
123 
124     // Refer to GpuConv2d::validate_op() for id-validness of this TensorInfo object
125     TensorInfo dst_info_to_validate;
126 
127     // Auto initialize dst tensor info
128     calculate_and_init_dst_if_empty(&dst_info_to_validate, src, attributes);
129 
130     // Perform fusion test
131     // Pack tensor infos
132     ArgumentPack<ITensorInfo> tensors;
133     tensors.add_const_tensor(ACL_SRC_0, src);
134     tensors.add_const_tensor(ACL_DST_0, &dst_info_to_validate);
135     const Operator op = sketch.implementation().operator_group().new_operator(operator_type, tensors);
136 
137     ARM_COMPUTE_RETURN_ERROR_ON_MSG(!sketch.implementation().operator_group().try_add_operator(op),
138                                     "Operator fusion test failed. This operator cannot be fused into the workload");
139 
140     // Check if configuration is supported
141     return is_supported_op_helper(*sketch.gpu_context(), src, &dst_info_to_validate, attributes);
142 }
143 
create_op(GpuWorkloadSketch & sketch,ITensorInfo * src,const GpuResize::Attributes & attributes)144 ITensorInfo *GpuResize::create_op(GpuWorkloadSketch           &sketch,
145                                   ITensorInfo                 *src,
146                                   const GpuResize::Attributes &attributes)
147 {
148     ARM_COMPUTE_ERROR_ON_NULLPTR(src);
149     ARM_COMPUTE_LOG_PARAMS(src, attributes);
150     ARM_COMPUTE_ERROR_THROW_ON(GpuResize::validate_op(sketch, src, attributes));
151 
152     ITensorInfo *dst = sketch.implementation().create_virtual_tensor();
153     ARM_COMPUTE_ERROR_ON_NULLPTR(dst);
154 
155     // Auto initialize dst tensor info if empty
156     calculate_and_init_dst_if_empty(dst, src, attributes);
157 
158     // Translate into components and add to component graph
159     GpuKernelComponentGraph &comp_graph = sketch.implementation().component_graph();
160     const auto              *sketch_ctx = sketch.implementation().context();
161 
162     if(sketch_ctx->gpu_language() == GpuLanguage::OpenCL)
163     {
164         ARM_COMPUTE_ERROR_ON_NULLPTR(sketch_ctx->cl_compile_context());
165 
166         // Add Resize Component
167         {
168             const auto properties = IGpuKernelComponent::Properties().stage(UnitWorkloadStage{ UnitWorkloadStage::Stage::Run });
169 
170             ArgumentPack<ITensorInfo> arguments;
171             arguments.add_const_tensor(ACL_SRC_0, src);
172             arguments.add_const_tensor(ACL_DST_0, dst);
173             comp_graph.add_new_component<ClComponentResize>(properties, arguments, attributes);
174         }
175     }
176     else
177     {
178         ARM_COMPUTE_ERROR("Unimplemented Gpu language");
179     }
180 
181     // Set up fusion test by adding to the Operator Group
182     // Note this has to be performed after all the components have been successfully added to the component graph
183 
184     // Pack tensor infos
185     ArgumentPack<ITensorInfo> tensors;
186     tensors.add_const_tensor(ACL_SRC_0, src);
187     tensors.add_const_tensor(ACL_DST_0, dst);
188 
189     const Operator op = sketch.implementation().operator_group().new_operator(operator_type, tensors);
190     sketch.implementation().operator_group().add_operator(op);
191 
192     return dst;
193 }
194 
195 } // namespace dynamic_fusion
196 } // namespace experimental
197 } // namespace arm_compute
198