• 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/CLMagnitudePhaseKernel.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/Helpers.h"
31 #include "arm_compute/core/TensorInfo.h"
32 #include "arm_compute/core/Validate.h"
33 #include "src/core/helpers/WindowHelpers.h"
34 #include "support/StringSupport.h"
35 
36 #include <set>
37 #include <string>
38 
39 using namespace arm_compute;
40 
CLMagnitudePhaseKernel()41 CLMagnitudePhaseKernel::CLMagnitudePhaseKernel()
42     : _gx(nullptr), _gy(nullptr), _magnitude(nullptr), _phase(nullptr), _run_mag(false), _run_phase(false)
43 {
44 }
45 
configure(const ICLTensor * gx,const ICLTensor * gy,ICLTensor * magnitude,ICLTensor * phase,MagnitudeType mag_type,PhaseType phase_type)46 void CLMagnitudePhaseKernel::configure(const ICLTensor *gx, const ICLTensor *gy, ICLTensor *magnitude, ICLTensor *phase,
47                                        MagnitudeType mag_type, PhaseType phase_type)
48 {
49     configure(CLKernelLibrary::get().get_compile_context(), gx, gy, magnitude, phase, mag_type, phase_type);
50 }
51 
configure(const CLCompileContext & compile_context,const ICLTensor * gx,const ICLTensor * gy,ICLTensor * magnitude,ICLTensor * phase,MagnitudeType mag_type,PhaseType phase_type)52 void CLMagnitudePhaseKernel::configure(const CLCompileContext &compile_context, const ICLTensor *gx, const ICLTensor *gy, ICLTensor *magnitude, ICLTensor *phase,
53                                        MagnitudeType mag_type, PhaseType phase_type)
54 {
55     ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(gx, 1, DataType::S16, DataType::S32);
56     ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(gy, 1, DataType::S16, DataType::S32);
57     ARM_COMPUTE_ERROR_ON((magnitude == nullptr) && (phase == nullptr));
58     ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(gx, gy);
59 
60     _run_mag   = (magnitude != nullptr);
61     _run_phase = (phase != nullptr);
62     if(_run_mag)
63     {
64         ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(magnitude, 1, DataType::S16, DataType::S32);
65         ARM_COMPUTE_ERROR_ON_MISMATCHING_DATA_TYPES(gx, magnitude);
66     }
67     if(_run_phase)
68     {
69         ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(phase, 1, DataType::U8);
70     }
71 
72     if(!_run_mag && !_run_phase)
73     {
74         ARM_COMPUTE_ERROR("At least one output must be NOT NULL");
75     }
76 
77     _gx        = gx;
78     _gy        = gy;
79     _magnitude = magnitude;
80     _phase     = phase;
81 
82     // Construct kernel name
83     std::set<std::string> build_opts = {};
84 
85     // Add magnitude type
86     if(_run_mag)
87     {
88         switch(mag_type)
89         {
90             case MagnitudeType::L1NORM:
91                 build_opts.insert("-DMAGNITUDE=1");
92                 break;
93             case MagnitudeType::L2NORM:
94                 build_opts.insert("-DMAGNITUDE=2");
95                 break;
96             default:
97                 ARM_COMPUTE_ERROR("Unsupported magnitude calculation type.");
98                 build_opts.insert("-DMAGNITUDE=0");
99                 break;
100         }
101     }
102 
103     // Add phase type
104     if(_run_phase)
105     {
106         switch(phase_type)
107         {
108             case PhaseType::UNSIGNED:
109                 build_opts.insert("-DPHASE=1");
110                 break;
111             case PhaseType::SIGNED:
112                 build_opts.insert("-DPHASE=2");
113                 break;
114             default:
115                 ARM_COMPUTE_ERROR("Unsupported phase calculation type.");
116                 build_opts.insert("-DPHASE=0");
117                 break;
118         }
119     }
120 
121     // Add data_type
122     build_opts.insert("-DDATA_TYPE=" + get_cl_type_from_data_type(gx->info()->data_type()));
123 
124     // Create kernel
125     const std::string kernel_name = std::string("magnitude_phase");
126     _kernel                       = create_kernel(compile_context, kernel_name, build_opts);
127 
128     // Configure kernel window
129     constexpr unsigned int num_elems_processed_per_iteration = 16;
130 
131     Window win = calculate_max_window(*gx->info(), Steps(num_elems_processed_per_iteration));
132 
133     AccessWindowHorizontal gx_access(gx->info(), 0, num_elems_processed_per_iteration);
134     AccessWindowHorizontal gy_access(gy->info(), 0, num_elems_processed_per_iteration);
135     AccessWindowHorizontal output_magnitude_access(magnitude == nullptr ? nullptr : magnitude->info(), 0, num_elems_processed_per_iteration);
136     AccessWindowHorizontal output_phase_access(phase == nullptr ? nullptr : phase->info(), 0, num_elems_processed_per_iteration);
137 
138     update_window_and_padding(win,
139                               gx_access, gy_access,
140                               output_magnitude_access, output_phase_access);
141 
142     ValidRegion valid_region = intersect_valid_regions(gx->info()->valid_region(),
143                                                        gy->info()->valid_region());
144     output_magnitude_access.set_valid_region(win, valid_region);
145     output_phase_access.set_valid_region(win, valid_region);
146 
147     ICLKernel::configure_internal(win);
148 
149     // Set config_id for enabling LWS tuning
150     _config_id = kernel_name;
151     _config_id += "_";
152     _config_id += lower_string(string_from_data_type(gx->info()->data_type()));
153     _config_id += "_";
154     _config_id += support::cpp11::to_string(gx->info()->dimension(0));
155     _config_id += "_";
156     _config_id += support::cpp11::to_string(gx->info()->dimension(1));
157 }
158 
run(const Window & window,cl::CommandQueue & queue)159 void CLMagnitudePhaseKernel::run(const Window &window, cl::CommandQueue &queue)
160 {
161     ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(this);
162     ARM_COMPUTE_ERROR_ON_INVALID_SUBWINDOW(ICLKernel::window(), window);
163 
164     Window slice = window.first_slice_window_2D();
165     do
166     {
167         unsigned int idx = 0;
168         add_2D_tensor_argument(idx, _gx, slice);
169         add_2D_tensor_argument(idx, _gy, slice);
170         add_2D_tensor_argument_if((_run_mag), idx, _magnitude, slice);
171         add_2D_tensor_argument_if((_run_phase), idx, _phase, slice);
172 
173         enqueue(queue, *this, slice, lws_hint());
174     }
175     while(window.slide_window_slice_2D(slice));
176 }
177