• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2016-2020 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 #include "src/core/CL/kernels/CLDepthConvertLayerKernel.h"
25 
26 #include "arm_compute/core/CL/CLHelpers.h"
27 #include "arm_compute/core/CL/CLKernelLibrary.h"
28 #include "arm_compute/core/CL/ICLTensor.h"
29 #include "arm_compute/core/CL/OpenCL.h"
30 #include "arm_compute/core/TensorInfo.h"
31 #include "arm_compute/core/Utils.h"
32 #include "arm_compute/core/Validate.h"
33 #include "src/core/CL/CLValidate.h"
34 #include "src/core/helpers/AutoConfiguration.h"
35 #include "src/core/helpers/WindowHelpers.h"
36 #include "support/StringSupport.h"
37 
38 #include <cstddef>
39 #include <set>
40 #include <string>
41 
42 namespace arm_compute
43 {
44 namespace
45 {
validate_arguments(const ITensorInfo * input,const ITensorInfo * output,ConvertPolicy policy,uint32_t shift)46 Status validate_arguments(const ITensorInfo *input, const ITensorInfo *output, ConvertPolicy policy, uint32_t shift)
47 {
48     ARM_COMPUTE_UNUSED(policy);
49     ARM_COMPUTE_RETURN_ERROR_ON_F16_UNSUPPORTED(input);
50     ARM_COMPUTE_RETURN_ERROR_ON(input == output);
51     ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input,
52                                                          1,
53                                                          DataType::U8, DataType::S8, DataType::QSYMM8_PER_CHANNEL, DataType::S16,
54                                                          DataType::U16, DataType::U32, DataType::S32, DataType::F16,
55                                                          DataType::F32);
56     ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(output,
57                                                          1,
58                                                          DataType::U8, DataType::S8, DataType::QASYMM8, DataType::S16,
59                                                          DataType::U16, DataType::U32, DataType::S32, DataType::F16,
60                                                          DataType::F32);
61     ARM_COMPUTE_RETURN_ERROR_ON_MSG(input->data_type() == output->data_type(), "Input and output data types must be different");
62     ARM_COMPUTE_RETURN_ERROR_ON_MSG(is_data_type_float(input->data_type()) && shift != 0, "Shift is used only with integer non-quantized inputs");
63     ARM_COMPUTE_RETURN_ERROR_ON_MSG(is_data_type_quantized(input->data_type()) && shift != 0, "Shift is used only with integer non-quantized inputs");
64     ARM_COMPUTE_RETURN_ERROR_ON(shift >= 8);
65 
66     // Validate in case of configured output
67     if(output->total_size() > 0)
68     {
69         ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_SHAPES(input, output);
70     }
71 
72     return Status{};
73 }
74 } // namespace
75 
configure(const ICLTensor * input,ICLTensor * output,ConvertPolicy policy,uint32_t shift)76 void CLDepthConvertLayerKernel::configure(const ICLTensor *input, ICLTensor *output, ConvertPolicy policy, uint32_t shift)
77 {
78     configure(CLKernelLibrary::get().get_compile_context(), input, output, policy, shift);
79 }
80 
configure(const CLCompileContext & compile_context,const ICLTensor * input,ICLTensor * output,ConvertPolicy policy,uint32_t shift)81 void CLDepthConvertLayerKernel::configure(const CLCompileContext &compile_context, const ICLTensor *input, ICLTensor *output, ConvertPolicy policy, uint32_t shift)
82 {
83     ARM_COMPUTE_ERROR_ON_NULLPTR(input, output);
84 
85     _input  = input;
86     _output = output;
87 
88     // Auto initialize output shape if not initialized (We can only auto-configure the shape, datatype must be given)
89     set_shape_if_empty(*output->info(), input->info()->tensor_shape());
90 
91     ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(input->info(), output->info(), policy, shift));
92 
93     auto padding_info = get_padding_info({ input, output });
94 
95     // Get data sizes
96     const size_t input_size  = data_size_from_type(input->info()->data_type());
97     const size_t output_size = data_size_from_type(output->info()->data_type());
98 
99     // Get number of elements to process per iterations
100     const unsigned int num_elems_processed_per_iteration = adjust_vec_size(16 / input->info()->element_size(), input->info()->dimension(0));
101 
102     // Set build options
103     CLBuildOptions build_opts;
104     build_opts.add_option("-DVEC_SIZE=" + support::cpp11::to_string(num_elems_processed_per_iteration));
105     build_opts.add_option("-DVEC_SIZE_LEFTOVER=" + support::cpp11::to_string(input->info()->dimension(0) % num_elems_processed_per_iteration));
106     build_opts.add_option("-DDATA_TYPE_IN=" + get_cl_type_from_data_type(input->info()->data_type()));
107     build_opts.add_option("-DDATA_TYPE_OUT=" + get_cl_type_from_data_type(output->info()->data_type()));
108     // Conversions from float always SATURATE as out-of-bounds conversion from float->integer is implementation defined
109     build_opts.add_option_if(is_data_type_float(input->info()->data_type()) || policy == ConvertPolicy::SATURATE, "-DSATURATE");
110     build_opts.add_option_if(is_data_type_float(input->info()->data_type()) || is_data_type_float(output->info()->data_type()), "-DIS_DATA_TYPE_FLOAT");
111     build_opts.add_option_if(is_data_type_quantized(input->info()->data_type()), "-DIS_DATA_TYPE_QUANTIZED");
112 
113     // Create kernel
114     const std::string kernel_name = (input_size >= output_size) ? "convert_depth_down" : "convert_depth_up";
115     _kernel                       = create_kernel(compile_context, kernel_name, build_opts.options());
116 
117     // Set shift arg
118     unsigned int idx = 2 * num_arguments_per_3D_tensor(); // Skip the input and output parameters
119     _kernel.setArg(idx++, shift);
120 
121     // Since we have a leftover vector size calculated using the input tensor shape, it is required to
122     // have the input region equal to the tensor shape
123     ValidRegion input_valid_region = input->info()->valid_region();
124     input->info()->set_valid_region(ValidRegion(Coordinates(0, 0), input->info()->tensor_shape()));
125 
126     // Configure kernel
127     Window win = calculate_max_window(*input->info(), Steps(num_elems_processed_per_iteration));
128     ICLKernel::configure_internal(win);
129 
130     // Collapse window
131     const Window &full_window      = window();
132     Window        collapsed_window = full_window.collapse_if_possible(full_window, Window::DimZ);
133     ICLKernel::configure_internal(collapsed_window);
134 
135     // Restore the valid region
136     input->info()->set_valid_region(input_valid_region);
137 
138     ARM_COMPUTE_ERROR_ON(has_padding_changed(padding_info));
139 
140     // Set config_id for enabling LWS tuning
141     _config_id = kernel_name;
142     _config_id += "_";
143     _config_id += lower_string(string_from_data_type(input->info()->data_type()));
144     _config_id += "_";
145     _config_id += support::cpp11::to_string(input->info()->dimension(0));
146     _config_id += "_";
147     _config_id += support::cpp11::to_string(input->info()->dimension(1));
148     _config_id += "_";
149     _config_id += support::cpp11::to_string(output->info()->dimension(0));
150     _config_id += "_";
151     _config_id += support::cpp11::to_string(output->info()->dimension(1));
152 }
153 
validate(const ITensorInfo * input,const ITensorInfo * output,ConvertPolicy policy,uint32_t shift)154 Status CLDepthConvertLayerKernel::validate(const ITensorInfo *input, const ITensorInfo *output, ConvertPolicy policy, uint32_t shift)
155 {
156     ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(input, output, policy, shift));
157 
158     return Status{};
159 }
160 } // namespace arm_compute
161