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