1 /*
2 * Copyright (c) 2018-2021 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 "arm_compute/runtime/CL/functions/CLElementwiseOperations.h"
25
26 #include "arm_compute/core/CL/CLKernelLibrary.h"
27 #include "arm_compute/core/CL/ICLTensor.h"
28 #include "arm_compute/core/Types.h"
29 #include "src/core/CL/ICLKernel.h"
30
31 #include "src/gpu/cl/operators/ClAdd.h"
32 #include "src/gpu/cl/operators/ClElementwiseOperations.h"
33 #include "src/gpu/cl/operators/ClSub.h"
34
35 namespace arm_compute
36 {
37 struct CLArithmeticAddition::Impl
38 {
39 const ICLTensor *src_0{ nullptr };
40 const ICLTensor *src_1{ nullptr };
41 ICLTensor *dst{ nullptr };
42 std::unique_ptr<opencl::ClAdd> op{ nullptr };
43 };
44
CLArithmeticAddition()45 CLArithmeticAddition::CLArithmeticAddition()
46 : _impl(std::make_unique<Impl>())
47 {
48 }
49 CLArithmeticAddition::CLArithmeticAddition(CLArithmeticAddition &&) = default;
50 CLArithmeticAddition &CLArithmeticAddition::operator=(CLArithmeticAddition &&) = default;
51 CLArithmeticAddition::~CLArithmeticAddition() = default;
52
configure(ICLTensor * input1,ICLTensor * input2,ICLTensor * output,ConvertPolicy policy,const ActivationLayerInfo & act_info)53 void CLArithmeticAddition::configure(ICLTensor *input1, ICLTensor *input2, ICLTensor *output, ConvertPolicy policy, const ActivationLayerInfo &act_info)
54 {
55 configure(CLKernelLibrary::get().get_compile_context(), input1, input2, output, policy, act_info);
56 }
57
configure(const CLCompileContext & compile_context,const ICLTensor * input1,const ICLTensor * input2,ICLTensor * output,ConvertPolicy policy,const ActivationLayerInfo & act_info)58 void CLArithmeticAddition::configure(const CLCompileContext &compile_context, const ICLTensor *input1, const ICLTensor *input2, ICLTensor *output, ConvertPolicy policy,
59 const ActivationLayerInfo &act_info)
60 {
61 _impl->src_0 = input1;
62 _impl->src_1 = input2;
63 _impl->dst = output;
64 _impl->op = std::make_unique<opencl::ClAdd>();
65 _impl->op->configure(compile_context, input1->info(), input2->info(), output->info(), policy, act_info);
66 }
67
validate(const ITensorInfo * input1,const ITensorInfo * input2,const ITensorInfo * output,ConvertPolicy policy,const ActivationLayerInfo & act_info)68 Status CLArithmeticAddition::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output, ConvertPolicy policy, const ActivationLayerInfo &act_info)
69 {
70 return opencl::ClAdd::validate(input1, input2, output, policy, act_info);
71 }
72
run()73 void CLArithmeticAddition::run()
74 {
75 ITensorPack pack;
76 pack.add_tensor(TensorType::ACL_SRC_0, _impl->src_0);
77 pack.add_tensor(TensorType::ACL_SRC_1, _impl->src_1);
78 pack.add_tensor(TensorType::ACL_DST, _impl->dst);
79
80 _impl->op->run(pack);
81 }
82
83 struct CLArithmeticSubtraction::Impl
84 {
85 const ICLTensor *src_0{ nullptr };
86 const ICLTensor *src_1{ nullptr };
87 ICLTensor *dst{ nullptr };
88 std::unique_ptr<opencl::ClSub> op{ nullptr };
89 };
90
CLArithmeticSubtraction()91 CLArithmeticSubtraction::CLArithmeticSubtraction()
92 : _impl(std::make_unique<Impl>())
93 {
94 }
95 CLArithmeticSubtraction::CLArithmeticSubtraction(CLArithmeticSubtraction &&) = default;
96 CLArithmeticSubtraction &CLArithmeticSubtraction::operator=(CLArithmeticSubtraction &&) = default;
97 CLArithmeticSubtraction::~CLArithmeticSubtraction() = default;
98
configure(const ICLTensor * input1,const ICLTensor * input2,ICLTensor * output,ConvertPolicy policy,const ActivationLayerInfo & act_info)99 void CLArithmeticSubtraction::configure(const ICLTensor *input1, const ICLTensor *input2, ICLTensor *output, ConvertPolicy policy, const ActivationLayerInfo &act_info)
100 {
101 configure(CLKernelLibrary::get().get_compile_context(), input1, input2, output, policy, act_info);
102 }
103
configure(const CLCompileContext & compile_context,const ICLTensor * input1,const ICLTensor * input2,ICLTensor * output,ConvertPolicy policy,const ActivationLayerInfo & act_info)104 void CLArithmeticSubtraction::configure(const CLCompileContext &compile_context, const ICLTensor *input1, const ICLTensor *input2, ICLTensor *output, ConvertPolicy policy,
105 const ActivationLayerInfo &act_info)
106 {
107 _impl->src_0 = input1;
108 _impl->src_1 = input2;
109 _impl->dst = output;
110 _impl->op = std::make_unique<opencl::ClSub>();
111 _impl->op->configure(compile_context, input1->info(), input2->info(), output->info(), policy, act_info);
112 }
113
validate(const ITensorInfo * input1,const ITensorInfo * input2,const ITensorInfo * output,ConvertPolicy policy,const ActivationLayerInfo & act_info)114 Status CLArithmeticSubtraction::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output, ConvertPolicy policy, const ActivationLayerInfo &act_info)
115 {
116 return opencl::ClSub::validate(input1, input2, output, policy, act_info);
117 }
118
run()119 void CLArithmeticSubtraction::run()
120 {
121 ITensorPack pack;
122 pack.add_tensor(TensorType::ACL_SRC_0, _impl->src_0);
123 pack.add_tensor(TensorType::ACL_SRC_1, _impl->src_1);
124 pack.add_tensor(TensorType::ACL_DST, _impl->dst);
125
126 _impl->op->run(pack);
127 }
128
129 struct CLArithmeticDivision::Impl
130 {
131 const ICLTensor *src_0{ nullptr };
132 const ICLTensor *src_1{ nullptr };
133 ICLTensor *dst{ nullptr };
134 std::unique_ptr<opencl::ClElementwiseDivision> op{ nullptr };
135 };
136
CLArithmeticDivision()137 CLArithmeticDivision::CLArithmeticDivision()
138 : _impl(std::make_unique<Impl>())
139 {
140 }
141 CLArithmeticDivision::CLArithmeticDivision(CLArithmeticDivision &&) = default;
142 CLArithmeticDivision &CLArithmeticDivision::operator=(CLArithmeticDivision &&) = default;
143 CLArithmeticDivision::~CLArithmeticDivision() = default;
144
configure(ICLTensor * input1,ICLTensor * input2,ICLTensor * output,const ActivationLayerInfo & act_info)145 void CLArithmeticDivision::configure(ICLTensor *input1, ICLTensor *input2, ICLTensor *output, const ActivationLayerInfo &act_info)
146 {
147 configure(CLKernelLibrary::get().get_compile_context(), input1, input2, output, act_info);
148 }
149
configure(const CLCompileContext & compile_context,const ICLTensor * input1,const ICLTensor * input2,ICLTensor * output,const ActivationLayerInfo & act_info)150 void CLArithmeticDivision::configure(const CLCompileContext &compile_context, const ICLTensor *input1, const ICLTensor *input2, ICLTensor *output, const ActivationLayerInfo &act_info)
151 {
152 _impl->src_0 = input1;
153 _impl->src_1 = input2;
154 _impl->dst = output;
155 _impl->op = std::make_unique<opencl::ClElementwiseDivision>();
156 _impl->op->configure(compile_context, input1->info(), input2->info(), output->info(), act_info);
157 }
158
validate(const ITensorInfo * input1,const ITensorInfo * input2,const ITensorInfo * output,const ActivationLayerInfo & act_info)159 Status CLArithmeticDivision::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output, const ActivationLayerInfo &act_info)
160 {
161 return opencl::ClElementwiseDivision::validate(input1, input2, output, act_info);
162 }
163
run()164 void CLArithmeticDivision::run()
165 {
166 ITensorPack pack;
167 pack.add_tensor(TensorType::ACL_SRC_0, _impl->src_0);
168 pack.add_tensor(TensorType::ACL_SRC_1, _impl->src_1);
169 pack.add_tensor(TensorType::ACL_DST, _impl->dst);
170
171 _impl->op->run(pack);
172 }
173
174 struct CLElementwiseMax::Impl
175 {
176 const ICLTensor *src_0{ nullptr };
177 const ICLTensor *src_1{ nullptr };
178 ICLTensor *dst{ nullptr };
179 std::unique_ptr<opencl::ClElementwiseMax> op{ nullptr };
180 };
181
CLElementwiseMax()182 CLElementwiseMax::CLElementwiseMax()
183 : _impl(std::make_unique<Impl>())
184 {
185 }
186 CLElementwiseMax::CLElementwiseMax(CLElementwiseMax &&) = default;
187 CLElementwiseMax &CLElementwiseMax::operator=(CLElementwiseMax &&) = default;
188 CLElementwiseMax::~CLElementwiseMax() = default;
189
configure(ICLTensor * input1,ICLTensor * input2,ICLTensor * output,const ActivationLayerInfo & act_info)190 void CLElementwiseMax::configure(ICLTensor *input1, ICLTensor *input2, ICLTensor *output, const ActivationLayerInfo &act_info)
191 {
192 configure(CLKernelLibrary::get().get_compile_context(), input1, input2, output, act_info);
193 }
194
configure(const CLCompileContext & compile_context,ICLTensor * input1,ICLTensor * input2,ICLTensor * output,const ActivationLayerInfo & act_info)195 void CLElementwiseMax::configure(const CLCompileContext &compile_context, ICLTensor *input1, ICLTensor *input2, ICLTensor *output, const ActivationLayerInfo &act_info)
196 {
197 _impl->src_0 = input1;
198 _impl->src_1 = input2;
199 _impl->dst = output;
200 _impl->op = std::make_unique<opencl::ClElementwiseMax>();
201 _impl->op->configure(compile_context, input1->info(), input2->info(), output->info(), act_info);
202 }
203
validate(const ITensorInfo * input1,const ITensorInfo * input2,const ITensorInfo * output,const ActivationLayerInfo & act_info)204 Status CLElementwiseMax::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output, const ActivationLayerInfo &act_info)
205 {
206 return opencl::ClElementwiseMax::validate(input1, input2, output, act_info);
207 }
208
run()209 void CLElementwiseMax::run()
210 {
211 ITensorPack pack;
212 pack.add_tensor(TensorType::ACL_SRC_0, _impl->src_0);
213 pack.add_tensor(TensorType::ACL_SRC_1, _impl->src_1);
214 pack.add_tensor(TensorType::ACL_DST, _impl->dst);
215
216 _impl->op->run(pack);
217 }
218
219 struct CLElementwiseMin::Impl
220 {
221 const ICLTensor *src_0{ nullptr };
222 const ICLTensor *src_1{ nullptr };
223 ICLTensor *dst{ nullptr };
224 std::unique_ptr<opencl::ClElementwiseMin> op{ nullptr };
225 };
226
CLElementwiseMin()227 CLElementwiseMin::CLElementwiseMin()
228 : _impl(std::make_unique<Impl>())
229 {
230 }
231 CLElementwiseMin::CLElementwiseMin(CLElementwiseMin &&) = default;
232 CLElementwiseMin &CLElementwiseMin::operator=(CLElementwiseMin &&) = default;
233 CLElementwiseMin::~CLElementwiseMin() = default;
234
configure(ICLTensor * input1,ICLTensor * input2,ICLTensor * output,const ActivationLayerInfo & act_info)235 void CLElementwiseMin::configure(ICLTensor *input1, ICLTensor *input2, ICLTensor *output, const ActivationLayerInfo &act_info)
236 {
237 configure(CLKernelLibrary::get().get_compile_context(), input1, input2, output, act_info);
238 }
239
configure(const CLCompileContext & compile_context,ICLTensor * input1,ICLTensor * input2,ICLTensor * output,const ActivationLayerInfo & act_info)240 void CLElementwiseMin::configure(const CLCompileContext &compile_context, ICLTensor *input1, ICLTensor *input2, ICLTensor *output, const ActivationLayerInfo &act_info)
241 {
242 _impl->src_0 = input1;
243 _impl->src_1 = input2;
244 _impl->dst = output;
245 _impl->op = std::make_unique<opencl::ClElementwiseMin>();
246 _impl->op->configure(compile_context, input1->info(), input2->info(), output->info(), act_info);
247 }
248
validate(const ITensorInfo * input1,const ITensorInfo * input2,const ITensorInfo * output,const ActivationLayerInfo & act_info)249 Status CLElementwiseMin::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output, const ActivationLayerInfo &act_info)
250 {
251 return opencl::ClElementwiseMin::validate(input1, input2, output, act_info);
252 }
253
run()254 void CLElementwiseMin::run()
255 {
256 ITensorPack pack;
257 pack.add_tensor(TensorType::ACL_SRC_0, _impl->src_0);
258 pack.add_tensor(TensorType::ACL_SRC_1, _impl->src_1);
259 pack.add_tensor(TensorType::ACL_DST, _impl->dst);
260
261 _impl->op->run(pack);
262 }
263
264 struct CLElementwiseSquaredDiff::Impl
265 {
266 const ICLTensor *src_0{ nullptr };
267 const ICLTensor *src_1{ nullptr };
268 ICLTensor *dst{ nullptr };
269 std::unique_ptr<opencl::ClElementwiseSquaredDiff> op{ nullptr };
270 };
271
CLElementwiseSquaredDiff()272 CLElementwiseSquaredDiff::CLElementwiseSquaredDiff()
273 : _impl(std::make_unique<Impl>())
274 {
275 }
276 CLElementwiseSquaredDiff::CLElementwiseSquaredDiff(CLElementwiseSquaredDiff &&) = default;
277 CLElementwiseSquaredDiff &CLElementwiseSquaredDiff::operator=(CLElementwiseSquaredDiff &&) = default;
278 CLElementwiseSquaredDiff::~CLElementwiseSquaredDiff() = default;
279
configure(ICLTensor * input1,ICLTensor * input2,ICLTensor * output,const ActivationLayerInfo & act_info)280 void CLElementwiseSquaredDiff::configure(ICLTensor *input1, ICLTensor *input2, ICLTensor *output, const ActivationLayerInfo &act_info)
281 {
282 configure(CLKernelLibrary::get().get_compile_context(), input1, input2, output, act_info);
283 }
284
configure(const CLCompileContext & compile_context,ICLTensor * input1,ICLTensor * input2,ICLTensor * output,const ActivationLayerInfo & act_info)285 void CLElementwiseSquaredDiff::configure(const CLCompileContext &compile_context, ICLTensor *input1, ICLTensor *input2, ICLTensor *output, const ActivationLayerInfo &act_info)
286 {
287 _impl->src_0 = input1;
288 _impl->src_1 = input2;
289 _impl->dst = output;
290 _impl->op = std::make_unique<opencl::ClElementwiseSquaredDiff>();
291 _impl->op->configure(compile_context, input1->info(), input2->info(), output->info(), act_info);
292 }
293
validate(const ITensorInfo * input1,const ITensorInfo * input2,const ITensorInfo * output,const ActivationLayerInfo & act_info)294 Status CLElementwiseSquaredDiff::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output, const ActivationLayerInfo &act_info)
295 {
296 return opencl::ClElementwiseSquaredDiff::validate(input1, input2, output, act_info);
297 }
298
run()299 void CLElementwiseSquaredDiff::run()
300 {
301 ITensorPack pack;
302 pack.add_tensor(TensorType::ACL_SRC_0, _impl->src_0);
303 pack.add_tensor(TensorType::ACL_SRC_1, _impl->src_1);
304 pack.add_tensor(TensorType::ACL_DST, _impl->dst);
305
306 _impl->op->run(pack);
307 }
308
309 struct CLElementwisePower::Impl
310 {
311 const ICLTensor *src_0{ nullptr };
312 const ICLTensor *src_1{ nullptr };
313 ICLTensor *dst{ nullptr };
314 std::unique_ptr<opencl::ClElementwisePower> op{ nullptr };
315 };
316
CLElementwisePower()317 CLElementwisePower::CLElementwisePower()
318 : _impl(std::make_unique<Impl>())
319 {
320 }
321 CLElementwisePower::CLElementwisePower(CLElementwisePower &&) = default;
322 CLElementwisePower &CLElementwisePower::operator=(CLElementwisePower &&) = default;
323 CLElementwisePower::~CLElementwisePower() = default;
324
configure(ICLTensor * input1,ICLTensor * input2,ICLTensor * output,const ActivationLayerInfo & act_info)325 void CLElementwisePower::configure(ICLTensor *input1, ICLTensor *input2, ICLTensor *output, const ActivationLayerInfo &act_info)
326 {
327 configure(CLKernelLibrary::get().get_compile_context(), input1, input2, output, act_info);
328 }
329
configure(const CLCompileContext & compile_context,ICLTensor * input1,ICLTensor * input2,ICLTensor * output,const ActivationLayerInfo & act_info)330 void CLElementwisePower::configure(const CLCompileContext &compile_context, ICLTensor *input1, ICLTensor *input2, ICLTensor *output, const ActivationLayerInfo &act_info)
331 {
332 _impl->src_0 = input1;
333 _impl->src_1 = input2;
334 _impl->dst = output;
335 _impl->op = std::make_unique<opencl::ClElementwisePower>();
336 _impl->op->configure(compile_context, input1->info(), input2->info(), output->info(), act_info);
337 }
338
validate(const ITensorInfo * input1,const ITensorInfo * input2,const ITensorInfo * output,const ActivationLayerInfo & act_info)339 Status CLElementwisePower::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output, const ActivationLayerInfo &act_info)
340 {
341 return opencl::ClElementwisePower::validate(input1, input2, output, act_info);
342 }
343
run()344 void CLElementwisePower::run()
345 {
346 ITensorPack pack;
347 pack.add_tensor(TensorType::ACL_SRC_0, _impl->src_0);
348 pack.add_tensor(TensorType::ACL_SRC_1, _impl->src_1);
349 pack.add_tensor(TensorType::ACL_DST, _impl->dst);
350
351 _impl->op->run(pack);
352 }
353 } // namespace arm_compute
354