blob: 263c57b16b307f6dc3948d9dc5de541b42f98e2f [file] [log] [blame]
Anthony Barbierdbdab852017-06-23 15:42:00 +01001/*
2 * Copyright (c) 2017 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 "Reference.h"
25
26#include "Globals.h"
27#include "Helpers.h"
28#include "ReferenceCPP.h"
29#include "TensorLibrary.h"
30#include "validation/Helpers.h"
31
32#include <random>
33
34using namespace arm_compute::test;
35
36namespace arm_compute
37{
38namespace test
39{
40namespace validation
41{
42RawTensor Reference::compute_reference_integral_image(const TensorShape &shape)
43{
44 // Create reference
45 RawTensor ref_src = library->get(shape, DataType::U8);
46 RawTensor ref_dst = library->get(shape, DataType::U32);
47
48 // Fill reference
49 library->fill_tensor_uniform(ref_src, 0);
50
51 // Compute reference
52 ReferenceCPP::integral_image(ref_src, ref_dst);
53
54 return ref_dst;
55}
56RawTensor Reference::compute_reference_absolute_difference(const TensorShape &shape, DataType dt_in0, DataType dt_in1, DataType dt_out)
57{
58 // Create reference
59 RawTensor ref_src1 = library->get(shape, dt_in0);
60 RawTensor ref_src2 = library->get(shape, dt_in1);
61 RawTensor ref_dst = library->get(shape, dt_out);
62
63 // Fill reference
64 library->fill_tensor_uniform(ref_src1, 0);
65 library->fill_tensor_uniform(ref_src2, 1);
66
67 // Compute reference
68 ReferenceCPP::absolute_difference(ref_src1, ref_src2, ref_dst);
69
70 return ref_dst;
71}
72
73RawTensor Reference::compute_reference_accumulate(const TensorShape &shape)
74{
75 // Create reference
76 RawTensor ref_src = library->get(shape, DataType::U8);
77 RawTensor ref_dst = library->get(shape, DataType::S16);
78
79 // Fill reference
80 library->fill_tensor_uniform(ref_src, 0);
81 library->fill_tensor_uniform(ref_dst, 1);
82
83 // Compute reference
84 ReferenceCPP::accumulate(ref_src, ref_dst);
85
86 return ref_dst;
87}
88
89RawTensor Reference::compute_reference_accumulate_squared(const TensorShape &shape, uint32_t shift)
90{
91 // Create reference
92 RawTensor ref_src = library->get(shape, DataType::U8);
93 RawTensor ref_dst = library->get(shape, DataType::S16);
94
95 // Fill reference
96 // ref_dst tensor filled with non-negative values
97 library->fill_tensor_uniform(ref_src, 0);
98 library->fill_tensor_uniform(ref_dst, 1, static_cast<int16_t>(0), std::numeric_limits<int16_t>::max());
99
100 // Compute reference
101 ReferenceCPP::accumulate_squared(ref_src, ref_dst, shift);
102
103 return ref_dst;
104}
105
106RawTensor Reference::compute_reference_accumulate_weighted(const TensorShape &shape, float alpha)
107{
108 // Create reference
109 RawTensor ref_src = library->get(shape, DataType::U8);
110 RawTensor ref_dst = library->get(shape, DataType::U8);
111
112 // Fill reference
113 library->fill_tensor_uniform(ref_src, 0);
114 library->fill_tensor_uniform(ref_dst, 1);
115
116 // Compute reference
117 ReferenceCPP::accumulate_weighted(ref_src, ref_dst, alpha);
118
119 return ref_dst;
120}
121
122RawTensor Reference::compute_reference_arithmetic_addition(const TensorShape &shape, DataType dt_in0, DataType dt_in1, DataType dt_out, ConvertPolicy convert_policy)
123{
124 // Create reference
125 RawTensor ref_src1 = library->get(shape, dt_in0);
126 RawTensor ref_src2 = library->get(shape, dt_in1);
127 RawTensor ref_dst = library->get(shape, dt_out);
128
129 // Fill reference
130 library->fill_tensor_uniform(ref_src1, 0);
131 library->fill_tensor_uniform(ref_src2, 1);
132
133 // Compute reference
134 ReferenceCPP::arithmetic_addition(ref_src1, ref_src2, ref_dst, convert_policy);
135
136 return ref_dst;
137}
138
139RawTensor Reference::compute_reference_arithmetic_subtraction(const TensorShape &shape, DataType dt_in0, DataType dt_in1, DataType dt_out, ConvertPolicy convert_policy)
140{
141 // Create reference
142 RawTensor ref_src1 = library->get(shape, dt_in0);
143 RawTensor ref_src2 = library->get(shape, dt_in1);
144 RawTensor ref_dst = library->get(shape, dt_out);
145
146 // Fill reference
147 library->fill_tensor_uniform(ref_src1, 0);
148 library->fill_tensor_uniform(ref_src2, 1);
149
150 // Compute reference
151 ReferenceCPP::arithmetic_subtraction(ref_src1, ref_src2, ref_dst, convert_policy);
152
153 return ref_dst;
154}
155
156RawTensor Reference::compute_reference_bitwise_and(const TensorShape &shape)
157{
158 // Create reference
159 RawTensor ref_src1 = library->get(shape, DataType::U8);
160 RawTensor ref_src2 = library->get(shape, DataType::U8);
161 RawTensor ref_dst = library->get(shape, DataType::U8);
162
163 // Fill reference
164 library->fill_tensor_uniform(ref_src1, 0);
165 library->fill_tensor_uniform(ref_src2, 1);
166
167 // Compute reference
168 ReferenceCPP::bitwise_and(ref_src1, ref_src2, ref_dst);
169
170 return ref_dst;
171}
172
173RawTensor Reference::compute_reference_bitwise_or(const TensorShape &shape)
174{
175 // Create reference
176 RawTensor ref_src1 = library->get(shape, DataType::U8);
177 RawTensor ref_src2 = library->get(shape, DataType::U8);
178 RawTensor ref_dst = library->get(shape, DataType::U8);
179
180 // Fill reference
181 library->fill_tensor_uniform(ref_src1, 0);
182 library->fill_tensor_uniform(ref_src2, 1);
183
184 // Compute reference
185 ReferenceCPP::bitwise_or(ref_src1, ref_src2, ref_dst);
186
187 return ref_dst;
188}
189
190RawTensor Reference::compute_reference_bitwise_xor(const TensorShape &shape)
191{
192 // Create reference
193 RawTensor ref_src1 = library->get(shape, DataType::U8);
194 RawTensor ref_src2 = library->get(shape, DataType::U8);
195 RawTensor ref_dst = library->get(shape, DataType::U8);
196
197 // Fill reference
198 library->fill_tensor_uniform(ref_src1, 0);
199 library->fill_tensor_uniform(ref_src2, 1);
200
201 // Compute reference
202 ReferenceCPP::bitwise_xor(ref_src1, ref_src2, ref_dst);
203
204 return ref_dst;
205}
206
207RawTensor Reference::compute_reference_bitwise_not(const TensorShape &shape)
208{
209 // Create reference
210 RawTensor ref_src = library->get(shape, DataType::U8);
211 RawTensor ref_dst = library->get(shape, DataType::U8);
212
213 // Fill reference
214 library->fill_tensor_uniform(ref_src, 0);
215
216 // Compute reference
217 ReferenceCPP::bitwise_not(ref_src, ref_dst);
218
219 return ref_dst;
220}
221
222RawTensor Reference::compute_reference_box3x3(const TensorShape &shape)
223{
224 // Create reference
225 RawTensor ref_src = library->get(shape, DataType::U8);
226 RawTensor ref_dst = library->get(shape, DataType::U8);
227
228 // Fill reference
229 library->fill_tensor_uniform(ref_src, 0);
230
231 // Compute reference
232 ReferenceCPP::box3x3(ref_src, ref_dst);
233
234 return ref_dst;
235}
236
237RawTensor Reference::compute_reference_depth_convert(const TensorShape &shape, DataType dt_in, DataType dt_out, ConvertPolicy policy, uint32_t shift, uint32_t fixed_point_position)
238{
239 RawTensor ref_src = library->get(shape, dt_in, 1, fixed_point_position);
240 RawTensor ref_dst = library->get(shape, dt_out, 1, fixed_point_position);
241
242 // Fill reference
243 library->fill_tensor_uniform(ref_src, 0);
244
245 // Compute reference
246 ReferenceCPP::depth_convert(ref_src, ref_dst, policy, shift);
247
248 return ref_dst;
249}
250
251RawTensor Reference::compute_reference_gemm(const TensorShape &src_shape1, const TensorShape &src_shape2, const TensorShape &src_shape3,
252 const TensorShape &dst_shape, float alpha, float beta, DataType dt, int fixed_point_position)
253{
254 RawTensor src1 = library->get(src_shape1, dt, 1, fixed_point_position);
255 RawTensor src2 = library->get(src_shape2, dt, 1, fixed_point_position);
256 RawTensor src3 = library->get(src_shape3, dt, 1, fixed_point_position);
257 RawTensor dst = library->get(dst_shape, dt, 1, fixed_point_position);
258
259 // Fill reference
260 if(dt == DataType::F32)
261 {
262 std::uniform_real_distribution<> distribution(-1.0f, 1.0f);
263 library->fill(src1, distribution, 0);
264 library->fill(src2, distribution, 1);
265 library->fill(src3, distribution, 2);
266 }
267 else
268 {
269 library->fill_tensor_uniform(src1, 0);
270 library->fill_tensor_uniform(src2, 1);
271 library->fill_tensor_uniform(src3, 2);
272 }
273
274 // Compute reference
275 ReferenceCPP::gemm(src1, src2, src3, dst, alpha, beta);
276
277 return dst;
278}
279
280RawTensor Reference::compute_reference_pixel_wise_multiplication(const TensorShape &shape, DataType dt_in0, DataType dt_in1, DataType dt_out, float scale, ConvertPolicy convert_policy,
281 RoundingPolicy rounding_policy)
282{
283 // Create reference
284 RawTensor ref_src1 = library->get(shape, dt_in0);
285 RawTensor ref_src2 = library->get(shape, dt_in1);
286 RawTensor ref_dst = library->get(shape, dt_out);
287
288 // Fill reference
289 library->fill_tensor_uniform(ref_src1, 0);
290 library->fill_tensor_uniform(ref_src2, 1);
291
292 // Compute reference
293 ReferenceCPP::pixel_wise_multiplication(ref_src1, ref_src2, ref_dst, scale, convert_policy, rounding_policy);
294
295 return ref_dst;
296}
297
298RawTensor Reference::compute_reference_fixed_point_pixel_wise_multiplication(const TensorShape &shape, DataType dt_in0, DataType dt_in1, DataType dt_out, float scale, int fixed_point_position,
299 ConvertPolicy convert_policy, RoundingPolicy rounding_policy)
300{
301 // Create reference
302 RawTensor ref_src1 = library->get(shape, dt_in0, 1, fixed_point_position);
303 RawTensor ref_src2 = library->get(shape, dt_in1, 1, fixed_point_position);
304 RawTensor ref_dst = library->get(shape, dt_out, 1, fixed_point_position);
305
306 // Fill reference
307 library->fill_tensor_uniform(ref_src1, 0);
308 library->fill_tensor_uniform(ref_src2, 1);
309
310 // Compute reference
311 ReferenceCPP::fixed_point_pixel_wise_multiplication(ref_src1, ref_src2, ref_dst, scale, convert_policy, rounding_policy);
312
313 return ref_dst;
314}
315
316RawTensor Reference::compute_reference_threshold(const TensorShape &shape, uint8_t threshold, uint8_t false_value, uint8_t true_value, ThresholdType type, uint8_t upper)
317{
318 // Create reference
319 RawTensor ref_src1 = library->get(shape, DataType::U8);
320 RawTensor ref_dst = library->get(shape, DataType::U8);
321
322 // Fill reference
323 library->fill_tensor_uniform(ref_src1, 0);
324
325 // Compute reference
326 ReferenceCPP::threshold(ref_src1, ref_dst, threshold, false_value, true_value, type, upper);
327
328 return ref_dst;
329}
330
331RawTensor Reference::compute_reference_activation_layer(const TensorShape &shape, DataType dt, ActivationLayerInfo act_info, int fixed_point_position)
332{
333 // Create reference
334 RawTensor ref_src = library->get(shape, dt, 1, fixed_point_position);
335 RawTensor ref_dst = library->get(shape, dt, 1, fixed_point_position);
336
337 // Fill reference
338 if(dt == DataType::F32)
339 {
340 float min_bound = 0;
341 float max_bound = 0;
342 std::tie(min_bound, max_bound) = get_activation_layer_test_bounds<float>(act_info.activation());
343 std::uniform_real_distribution<> distribution(min_bound, max_bound);
344 library->fill(ref_src, distribution, 0);
345 }
346 else
347 {
348 int min_bound = 0;
349 int max_bound = 0;
350 std::tie(min_bound, max_bound) = get_activation_layer_test_bounds<int8_t>(act_info.activation(), fixed_point_position);
351 std::uniform_int_distribution<> distribution(min_bound, max_bound);
352 library->fill(ref_src, distribution, 0);
353 }
354
355 // Compute reference
356 ReferenceCPP::activation_layer(ref_src, ref_dst, act_info);
357
358 return ref_dst;
359}
360
361RawTensor Reference::compute_reference_batch_normalization_layer(const TensorShape &shape0, const TensorShape &shape1, DataType dt, float epsilon, int fixed_point_position)
362{
363 // Create reference
364 RawTensor ref_src = library->get(shape0, dt, 1, fixed_point_position);
365 RawTensor ref_dst = library->get(shape0, dt, 1, fixed_point_position);
366 RawTensor ref_mean = library->get(shape1, dt, 1, fixed_point_position);
367 RawTensor ref_var = library->get(shape1, dt, 1, fixed_point_position);
368 RawTensor ref_beta = library->get(shape1, dt, 1, fixed_point_position);
369 RawTensor ref_gamma = library->get(shape1, dt, 1, fixed_point_position);
370
371 // Fill tensors with values from -1 to 1.
372 if(dt == DataType::F32)
373 {
374 float min_bound = 0.f;
375 float max_bound = 0.f;
376 std::tie(min_bound, max_bound) = get_batchnormalization_layer_test_bounds<float>();
377 std::uniform_real_distribution<> distribution(min_bound, max_bound);
378 std::uniform_real_distribution<> distribution_var(0, max_bound);
379 library->fill(ref_src, distribution, 0);
380 library->fill(ref_mean, distribution, 1);
381 library->fill(ref_var, distribution_var, 0);
382 library->fill(ref_beta, distribution, 3);
383 library->fill(ref_gamma, distribution, 4);
384 }
385 else
386 {
387 int min_bound = 0;
388 int max_bound = 0;
389 std::tie(min_bound, max_bound) = get_batchnormalization_layer_test_bounds<int8_t>(fixed_point_position);
390 std::uniform_int_distribution<> distribution(min_bound, max_bound);
391 std::uniform_int_distribution<> distribution_var(0, max_bound);
392 library->fill(ref_src, distribution, 0);
393 library->fill(ref_mean, distribution, 1);
394 library->fill(ref_var, distribution_var, 0);
395 library->fill(ref_beta, distribution, 3);
396 library->fill(ref_gamma, distribution, 4);
397 }
398
399 // Compute reference
400 ReferenceCPP::batch_normalization_layer(ref_src, ref_dst, ref_mean, ref_var, ref_beta, ref_gamma, epsilon, fixed_point_position);
401
402 return ref_dst;
403}
404
405RawTensor Reference::compute_reference_convolution_layer(const TensorShape &input_shape, const TensorShape &weights_shape, const TensorShape &bias_shape, const TensorShape &output_shape, DataType dt,
406 const PadStrideInfo &conv_info, int fixed_point_position)
407{
408 // Create reference
409 RawTensor ref_src = library->get(input_shape, dt, 1, fixed_point_position);
410 RawTensor ref_weights = library->get(weights_shape, dt, 1, fixed_point_position);
411 RawTensor ref_bias = library->get(bias_shape, dt, 1, fixed_point_position);
412 RawTensor ref_dst = library->get(output_shape, dt, 1, fixed_point_position);
413
414 // Fill reference
415 if(dt == DataType::F32)
416 {
417 std::uniform_real_distribution<> distribution(-1.0f, 1.0f);
418 library->fill(ref_src, distribution, 0);
419 library->fill(ref_weights, distribution, 1);
420 library->fill(ref_bias, distribution, 2);
421 }
422 else
423 {
424 library->fill_tensor_uniform(ref_src, 0);
425 library->fill_tensor_uniform(ref_weights, 1);
426 library->fill_tensor_uniform(ref_bias, 2);
427 }
428
429 // Compute reference
430 ReferenceCPP::convolution_layer(ref_src, ref_weights, ref_bias, ref_dst, conv_info);
431
432 return ref_dst;
433}
434
435RawTensor Reference::compute_reference_fully_connected_layer(const TensorShape &input_shape, const TensorShape &weights_shape, const TensorShape &bias_shape, const TensorShape &output_shape,
436 DataType dt, bool transpose_weights, int fixed_point_position)
437{
438 // Create reference
439 RawTensor ref_src = library->get(input_shape, dt, 1, fixed_point_position);
440 RawTensor ref_bias = library->get(bias_shape, dt, 1, fixed_point_position);
441 RawTensor ref_dst = library->get(output_shape, dt, 1, fixed_point_position);
442
443 // Swap the first and second dimension of weights' shape if transpose_weights is true
444 TensorShape ws = weights_shape;
445 if(transpose_weights)
446 {
447 const size_t dimx = ws.x();
448 ws.set(0, ws.y());
449 ws.set(1, dimx);
450 }
451
452 RawTensor ref_weights = library->get(ws, dt, 1, fixed_point_position);
453
454 // Fill reference
455 if(dt == DataType::F32)
456 {
457 std::uniform_real_distribution<> distribution(-1.0f, 1.0f);
458 library->fill(ref_src, distribution, 0);
459 library->fill(ref_weights, distribution, 1);
460 library->fill(ref_bias, distribution, 2);
461 }
462 else
463 {
464 library->fill_tensor_uniform(ref_src, 0);
465 library->fill_tensor_uniform(ref_weights, 1);
466 library->fill_tensor_uniform(ref_bias, 2);
467 }
468
469 // Compute reference
470 ReferenceCPP::fully_connected_layer(ref_src, ref_weights, ref_bias, ref_dst);
471
472 return ref_dst;
473}
474
475RawTensor Reference::compute_reference_normalization_layer(const TensorShape &shape, DataType dt, NormalizationLayerInfo norm_info, int fixed_point_position)
476{
477 // Create reference
478 RawTensor ref_src = library->get(shape, dt, 1, fixed_point_position);
479 RawTensor ref_dst = library->get(shape, dt, 1, fixed_point_position);
480
481 // Fill reference
482 if(dt == DataType::QS8)
483 {
484 const int8_t one_fixed_point = 1 << fixed_point_position;
485 const int8_t minus_one_fixed_point = -one_fixed_point;
486 library->fill_tensor_uniform(ref_src, 0, minus_one_fixed_point, one_fixed_point);
487 }
488 else
489 {
490 library->fill_tensor_uniform(ref_src, 0);
491 }
492
493 // Compute reference
494 ReferenceCPP::normalization_layer(ref_src, ref_dst, norm_info);
495
496 return ref_dst;
497}
498
499RawTensor Reference::compute_reference_pooling_layer(const TensorShape &shape_in, const TensorShape &shape_out, DataType dt, PoolingLayerInfo pool_info, int fixed_point_position)
500{
501 // Create reference
502 RawTensor ref_src = library->get(shape_in, dt, 1, fixed_point_position);
503 RawTensor ref_dst = library->get(shape_out, dt, 1, fixed_point_position);
504
505 // Fill reference
506 int min = 0;
507 int max = 0;
508 switch(dt)
509 {
510 case DataType::F32:
511 min = -1;
512 max = 1;
513 break;
514 case DataType::QS8:
515 min = -(1 << fixed_point_position);
516 max = (1 << fixed_point_position);
517 break;
518 default:
519 ARM_COMPUTE_ERROR("DataType not supported.");
520 }
521 std::uniform_real_distribution<> distribution(min, max);
522 library->fill(ref_src, distribution, 0.0);
523
524 // Compute reference
525 ReferenceCPP::pooling_layer(ref_src, ref_dst, pool_info, fixed_point_position);
526
527 return ref_dst;
528}
529
530RawTensor Reference::compute_reference_softmax_layer(const TensorShape &shape, DataType dt, int fixed_point_position)
531{
532 // Create reference
533 RawTensor ref_src = library->get(shape, dt, 1, fixed_point_position);
534 RawTensor ref_dst = library->get(shape, dt, 1, fixed_point_position);
535
536 // Fill reference
537 if(arm_compute::is_data_type_float(dt))
538 {
539 std::uniform_real_distribution<> distribution(-10, 10);
540 library->fill(ref_src, distribution, 0);
541 }
542 else
543 {
544 int one_fixed = 1 << fixed_point_position;
545 std::uniform_int_distribution<> distribution(-one_fixed, one_fixed);
546 library->fill(ref_src, distribution, 0);
547 }
548
549 // Compute reference
550 ReferenceCPP::softmax_layer(ref_src, ref_dst);
551
552 return ref_dst;
553}
554
555RawTensor Reference::compute_reference_fixed_point_operation(const TensorShape &shape, DataType dt_in, DataType dt_out, FixedPointOp op, int fixed_point_position)
556{
557 // Create reference
558 RawTensor ref_src = library->get(shape, dt_in, 1, fixed_point_position);
559 RawTensor ref_dst = library->get(shape, dt_out, 1, fixed_point_position);
560
561 // Fill reference
562 int min = 0;
563 int max = 0;
564 switch(op)
565 {
566 case(FixedPointOp::INV_SQRT):
567 min = 32;
568 max = 127;
569 break;
570 case(FixedPointOp::LOG):
571 min = (1 << (fixed_point_position - 1));
572 max = 63;
573 break;
574 case(FixedPointOp::EXP):
575 min = 1;
576 max = (1 << (fixed_point_position - 1));
577 break;
578 case(FixedPointOp::RECIPROCAL):
579 min = 15;
580 max = 100;
581 break;
582 default:
583 ARM_COMPUTE_ERROR("Fixed point operation not supported");
584 }
585 std::uniform_int_distribution<> distribution(min, max);
586 library->fill(ref_src, distribution, 0);
587
588 // Compute reference
589 ReferenceCPP::fixed_point_operation(ref_src, ref_dst, op);
590
591 return ref_dst;
592}
593
594} // namespace validation
595} // namespace test
596} // namespace arm_compute