Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / thirdparty / clDNN / tests / test_cases / batch_norm_gpu_test.cpp
1 /*
2 // Copyright (c) 2016 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16
17 ///////////////////////////////////////////////////////////////////////////////////////////////////
18 #include <gtest/gtest.h>
19 #include "api/CPP/memory.hpp"
20 #include <api/CPP/input_layout.hpp>
21 #include "api/CPP/batch_norm.hpp"
22 #include <api/CPP/topology.hpp>
23 #include <api/CPP/network.hpp>
24 #include <api/CPP/engine.hpp>
25 #include "test_utils/test_utils.h"
26 #include <api/CPP/reorder.hpp>
27 #include <api/CPP/data.hpp>
28 #include <api/CPP/mutable_data.hpp>
29
30 using namespace cldnn;
31 using namespace tests;
32
33 TEST(batch_normalization_gpu, basic_in2x3x2x2) {
34     //  Mean   : 3x2x2
35     //  Input  : 2x3x2x2
36     //  Output : 2x3x2x2
37
38     //  Input:
39     //  f0: b0:  1    2  -10   b1:   0    0     -11
40     //  f0: b0:  3    4  -14   b1:   0.5 -0.5   -15  
41     //  f1: b0:  5    6  -12   b1:   1.5  5.2   -13     
42     //  f1: b0:  7    8  -16   b1:   12   9     -17
43     //
44     //  Mean
45     //  f0: -3.3333
46     //  f1: -0.3583
47     //
48     //  Variance
49     //  f0: 44.9305
50     //  f1: 107.0624
51
52
53     const auto& engine = get_test_engine();
54
55     auto input = memory::allocate(engine, { data_types::f32, format::yxfb, { 2, 2, 3, 2 } });
56     auto mean = memory::allocate(engine, { data_types::f32, format::yxfb, { 1, 2, 1, 1 } });
57     auto variance = memory::allocate(engine, { data_types::f32, format::yxfb, { 1, 2, 1, 1 } });
58
59     float epsilon = 0.0001f;
60
61     topology topology;
62     topology.add(input_layout("input", input.get_layout()));
63     topology.add(data("mean", mean));
64     topology.add(data("variance", variance));
65     topology.add(batch_norm("batch_norm", "input", "mean", "variance", epsilon));
66
67     set_values(input, {
68         1.f, 0.f, 5.f, 1.5f,
69         2.f, 0.f, 6.f, 5.2f,
70         -10.f, -11.f, -12.f, -13.f,
71         3.f, 0.5f, 7.f, 12.f,
72         4.f, -0.5f, 8.f, 9.f,
73         -14.f, -15.f, -16.f, -17.f
74     });
75
76     set_values(mean, { -3.3333f, -0.3583f });
77     set_values(variance, { 44.9305f, 107.0624f });
78
79     network network(engine, topology);
80
81     network.set_input_data("input", input);
82
83     auto outputs = network.execute();
84
85     auto output = outputs.at("batch_norm").get_memory();
86     auto output_ptr = output.pointer<float>();
87
88     for (int j = 0; j < 2; ++j) { //F
89         float sum = 0, var = 0;
90         for (int i = 0; i < 2; ++i) { //B
91             for (int k = 0; k < 2; ++k) { //Y
92                 for (int l = 0; l < 3; ++l) { //X
93                     float data = output_ptr[i + 2*j + 2*2*l + 2*2*3*k];
94                     sum += data;
95                     var += data * data;
96                 }
97             }
98         }
99         sum /= 2 * 3 * 2;
100         var /= 2 * 3 * 2;
101
102         EXPECT_NEAR(sum, 0, 1e-03F);
103         EXPECT_NEAR(var, 1, 1e-03F);
104     }
105 }
106
107 TEST(batch_normalization_gpu, basic_in2x3x2x2_scale_shift) {
108         //  Mean   : 3x2x2
109         //  Input  : 2x3x2x2
110         //  Output : 2x3x2x2
111
112         //  Input:
113         //  f0: b0:  1    2  -10   b1:   0    0     -11
114         //  f0: b0:  3    4  -14   b1:   0.5 -0.5   -15  
115         //  f1: b0:  5    6  -12   b1:   1.5  5.2   -13     
116         //  f1: b0:  7    8  -16   b1:   12   9     -17
117         //
118         //  Mean
119         //  f0: -3.3333
120         //  f1: -0.3583
121         //
122         //  Variance
123         //  f0: 44.9305
124         //  f1: 107.0624
125         //
126         //  Scale
127         //  f0: 2.0
128         //  f1: 1.0
129         //
130         //  Shift
131         //  f0: 0.0
132         //  f1: 5.0
133
134
135
136         const auto& engine = get_test_engine();
137
138         auto input = memory::allocate(engine, { data_types::f32, format::yxfb,{ 2, 2, 3, 2 } });
139         auto mean = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
140         auto variance = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
141         auto scale = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
142         auto shift = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
143
144         float epsilon = 0.0001f;
145
146         topology topology;
147         topology.add(input_layout("input", input.get_layout()));
148         topology.add(data("mean", mean));
149         topology.add(data("variance", variance));
150         topology.add(data("scale", scale));
151         topology.add(data("shift", shift));
152         topology.add(batch_norm("batch_norm", "input", "mean", "variance", "scale", "shift",  epsilon));
153
154         set_values(input, {
155                 1.f, 0.f, 5.f, 1.5f,
156                 2.f, 0.f, 6.f, 5.2f,
157                 -10.f, -11.f, -12.f, -13.f,
158                 3.f, 0.5f, 7.f, 12.f,
159                 4.f, -0.5f, 8.f, 9.f,
160                 -14.f, -15.f, -16.f, -17.f
161         });
162
163         set_values(mean, { -3.3333f, -0.3583f });
164         set_values(variance, { 44.9305f, 107.0624f });
165         set_values(scale, { 2.f, 1.f });
166         set_values(shift, { 0.f, 5.f });
167
168         network network(engine, topology);
169
170         network.set_input_data("input", input);
171
172         auto outputs = network.execute();
173
174         auto output = outputs.at("batch_norm").get_memory();
175         auto output_ptr = output.pointer<float>();
176
177         for (int j = 0; j < 2; ++j) { //F
178                 float sum = 0, var = 0;
179
180                 auto scalep = scale.pointer<float>();
181                 auto shiftp = shift.pointer<float>();
182                 float scalef = scalep[j];
183                 float shiftf = shiftp[j];
184
185                 for (int i = 0; i < 2; ++i) { //B
186                         for (int k = 0; k < 2; ++k) { //Y
187                                 for (int l = 0; l < 3; ++l) { //X
188                                         float data = output_ptr[i + 2 * j + 2 * 2 * l + 2 * 2 * 3 * k];
189                                         data = (data - shiftf) / scalef;
190                                         sum += data;
191                                         var += data * data;
192                                 }
193                         }
194                 }
195                 sum /= 2 * 3 * 2; 
196                 var /= 2 * 3 * 2;
197
198                 EXPECT_NEAR(sum, 0, 1e-03F);
199                 EXPECT_NEAR(var, 1, 1e-03F);
200         }
201 }
202
203 TEST(batch_normalization_gpu, basic_in2x3x2x2_with_var_mean_calc) {
204     //  Mean   : 3x2x2
205     //  Input  : 2x3x2x2
206     //  Output : 2x3x2x2
207
208     //  Input:
209     //  f0: b0:  1    2  -10   b1:   0    0     -11
210     //  f0: b0:  3    4  -14   b1:   0.5 -0.5   -15  
211     //  f1: b0:  5    6  -12   b1:   1.5  5.2   -13     
212     //  f1: b0:  7    8  -16   b1:   12   9     -17
213     //
214     //  Mean
215     //  f0: -3.3333
216     //  f1: -0.3583
217     //
218     //  Variance
219     //  f0: 44.9305
220     //  f1: 107.0624
221
222
223     const auto& engine = get_test_engine();
224
225     auto input = memory::allocate(engine, { data_types::f32, format::yxfb,{ 2, 2, 3, 2 } });
226     auto inv_variance = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
227
228     float epsilon = 0.0001f;
229
230     topology topology;
231     topology.add(input_layout("input", input.get_layout()));
232     topology.add(mutable_data("inv_variance", inv_variance));
233     topology.add(batch_norm("batch_norm", "input", epsilon, "inv_variance"));
234
235     set_values(input, {
236         1.f, 0.f, 5.f, 1.5f,
237         2.f, 0.f, 6.f, 5.2f,
238         -10.f, -11.f, -12.f, -13.f,
239         3.f, 0.5f, 7.f, 12.f,
240         4.f, -0.5f, 8.f, 9.f,
241         -14.f, -15.f, -16.f, -17.f
242     });
243
244     network network(engine, topology);
245
246     network.set_input_data("input", input);
247
248     auto outputs = network.execute();
249
250     auto output = outputs.at("batch_norm").get_memory();
251     auto output_ptr = output.pointer<float>();
252
253     for (int j = 0; j < 2; ++j) { //F
254         float sum = 0, var = 0;
255         for (int i = 0; i < 2; ++i) { //B
256             for (int k = 0; k < 2; ++k) { //Y
257                 for (int l = 0; l < 3; ++l) { //X
258                     float data = output_ptr[i + 2 * j + 2 * 2 * l + 2 * 2 * 3 * k];
259                     sum += data;
260                     var += data * data;
261                 }
262             }
263         }
264         sum /= 2 * 3 * 2;
265         var /= 2 * 3 * 2;
266
267         EXPECT_NEAR(sum, 0, 1e-03F);
268         EXPECT_NEAR(var, 1, 1e-03F);
269     }
270 }
271
272 TEST(batch_normalization_gpu, basic_in2x3x2x2_with_var_mean_calc_no_inv_var) {
273     //  Mean   : 3x2x2
274     //  Input  : 2x3x2x2
275     //  Output : 2x3x2x2
276
277     //  Input:
278     //  f0: b0:  1    2  -10   b1:   0    0     -11
279     //  f0: b0:  3    4  -14   b1:   0.5 -0.5   -15  
280     //  f1: b0:  5    6  -12   b1:   1.5  5.2   -13     
281     //  f1: b0:  7    8  -16   b1:   12   9     -17
282     //
283     //  Mean
284     //  f0: -3.3333
285     //  f1: -0.3583
286     //
287     //  Variance
288     //  f0: 44.9305
289     //  f1: 107.0624
290
291
292     const auto& engine = get_test_engine();
293
294     auto input = memory::allocate(engine, { data_types::f32, format::yxfb,{ 2, 2, 3, 2 } });
295
296     float epsilon = 0.0001f;
297
298     topology topology;
299     topology.add(input_layout("input", input.get_layout()));
300     topology.add(batch_norm("batch_norm", "input", epsilon));
301
302     set_values(input, {
303         1.f, 0.f, 5.f, 1.5f,
304         2.f, 0.f, 6.f, 5.2f,
305         -10.f, -11.f, -12.f, -13.f,
306         3.f, 0.5f, 7.f, 12.f,
307         4.f, -0.5f, 8.f, 9.f,
308         -14.f, -15.f, -16.f, -17.f
309     });
310
311     network network(engine, topology);
312
313     network.set_input_data("input", input);
314
315     auto outputs = network.execute();
316
317     auto output = outputs.at("batch_norm").get_memory();
318     auto output_ptr = output.pointer<float>();
319
320     for (int j = 0; j < 2; ++j) { //F
321         float sum = 0, var = 0;
322         for (int i = 0; i < 2; ++i) { //B
323             for (int k = 0; k < 2; ++k) { //Y
324                 for (int l = 0; l < 3; ++l) { //X
325                     float data = output_ptr[i + 2 * j + 2 * 2 * l + 2 * 2 * 3 * k];
326                     sum += data;
327                     var += data * data;
328                 }
329             }
330         }
331         sum /= 2 * 3 * 2;
332         var /= 2 * 3 * 2;
333
334         EXPECT_NEAR(sum, 0, 1e-03F);
335         EXPECT_NEAR(var, 1, 1e-03F);
336     }
337 }
338
339 TEST(batch_normalization_gpu, basic_in2x3x2x2_with_var_mean_calc_scale_shift) {
340         //  Mean   : 3x2x2
341         //  Input  : 2x3x2x2
342         //  Output : 2x3x2x2
343
344         //  Input:
345         //  f0: b0:  1    2  -10   b1:   0    0     -11
346         //  f0: b0:  3    4  -14   b1:   0.5 -0.5   -15  
347         //  f1: b0:  5    6  -12   b1:   1.5  5.2   -13     
348         //  f1: b0:  7    8  -16   b1:   12   9     -17
349         //
350         //  Mean
351         //  f0: -3.3333
352         //  f1: -0.3583
353         //
354         //  Variance
355         //  f0: 44.9305
356         //  f1: 107.0624
357         //
358         //  Scale
359         //  f0: 2.0
360         //  f1: 1.0
361         //
362         //  Shift
363         //  f0: 0.0
364         //  f1: 5.0
365
366
367         const auto& engine = get_test_engine();
368
369         auto input = memory::allocate(engine, { data_types::f32, format::yxfb,{ 2, 2, 3, 2 } });
370         auto mean = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
371         auto scale = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
372         auto shift = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
373         auto inv_variance = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
374
375         float epsilon = 0.0001f;
376
377         topology topology;
378         topology.add(input_layout("input", input.get_layout()));
379         topology.add(data("scale", scale));
380         topology.add(data("shift", shift));
381         topology.add(mutable_data("inv_variance", inv_variance));
382         topology.add(batch_norm("batch_norm", "input", epsilon, "scale", "shift", "inv_variance"));
383
384         set_values(input, {
385                 1.f, 0.f, 5.f, 1.5f,
386                 2.f, 0.f, 6.f, 5.2f,
387                 -10.f, -11.f, -12.f, -13.f,
388                 3.f, 0.5f, 7.f, 12.f,
389                 4.f, -0.5f, 8.f, 9.f,
390                 -14.f, -15.f, -16.f, -17.f
391         });
392
393         set_values(scale, { 2.f, 1.f });
394         set_values(shift, { 0.f, 5.f });
395
396         network network(engine, topology);
397
398         network.set_input_data("input", input);
399
400         auto outputs = network.execute();
401
402         auto output = outputs.at("batch_norm").get_memory();
403         auto output_ptr = output.pointer<float>();
404
405         for (int j = 0; j < 2; ++j) { //F
406                 float sum = 0, var = 0;
407
408                 auto scalep = scale.pointer<float>();
409                 auto shiftp = shift.pointer<float>();
410                 float scalef = scalep[j];
411                 float shiftf = shiftp[j];
412
413                 for (int i = 0; i < 2; ++i) { //B
414                         for (int k = 0; k < 2; ++k) { //Y
415                                 for (int l = 0; l < 3; ++l) { //X
416                                         float data = output_ptr[i + 2 * j + 2 * 2 * l + 2 * 2 * 3 * k];
417                                         data = (data - shiftf) / scalef;
418                                         sum += data;
419                                         var += data * data;
420                                 }
421                         }
422                 }
423                 sum /= 2 * 3 * 2;
424                 var /= 2 * 3 * 2;
425
426                 EXPECT_NEAR(sum, 0, 1e-03F);
427                 EXPECT_NEAR(var, 1, 1e-03F);
428         }
429 }
430
431 TEST(batch_normalization_gpu, basic_in2x3x2x2_with_var_mean_calc_scale_shift_no_inv_var) {
432     //  Mean   : 3x2x2
433     //  Input  : 2x3x2x2
434     //  Output : 2x3x2x2
435
436     //  Input:
437     //  f0: b0:  1    2  -10   b1:   0    0     -11
438     //  f0: b0:  3    4  -14   b1:   0.5 -0.5   -15  
439     //  f1: b0:  5    6  -12   b1:   1.5  5.2   -13     
440     //  f1: b0:  7    8  -16   b1:   12   9     -17
441     //
442     //  Mean
443     //  f0: -3.3333
444     //  f1: -0.3583
445     //
446     //  Variance
447     //  f0: 44.9305
448     //  f1: 107.0624
449     //
450     //  Scale
451     //  f0: 2.0
452     //  f1: 1.0
453     //
454     //  Shift
455     //  f0: 0.0
456     //  f1: 5.0
457
458
459     const auto& engine = get_test_engine();
460
461     auto input = memory::allocate(engine, { data_types::f32, format::yxfb,{ 2, 2, 3, 2 } });
462     auto scale = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
463     auto shift = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
464
465     float epsilon = 0.0001f;
466
467     topology topology;
468     topology.add(input_layout("input", input.get_layout()));
469     topology.add(data("scale", scale));
470     topology.add(data("shift", shift));
471     topology.add(batch_norm("batch_norm", "input", epsilon, "scale", "shift"));
472
473     set_values(input, {
474         1.f, 0.f, 5.f, 1.5f,
475         2.f, 0.f, 6.f, 5.2f,
476         -10.f, -11.f, -12.f, -13.f,
477         3.f, 0.5f, 7.f, 12.f,
478         4.f, -0.5f, 8.f, 9.f,
479         -14.f, -15.f, -16.f, -17.f
480     });
481
482     set_values(scale, { 2.f, 1.f });
483     set_values(shift, { 0.f, 5.f });
484
485     network network(engine, topology);
486
487     network.set_input_data("input", input);
488
489     auto outputs = network.execute();
490
491     auto output = outputs.at("batch_norm").get_memory();
492     auto output_ptr = output.pointer<float>();
493
494     for (int j = 0; j < 2; ++j) { //F
495         float sum = 0, var = 0;
496
497         auto scalep = scale.pointer<float>();
498         auto shiftp = shift.pointer<float>();
499         float scalef = scalep[j];
500         float shiftf = shiftp[j];
501
502         for (int i = 0; i < 2; ++i) { //B
503             for (int k = 0; k < 2; ++k) { //Y
504                 for (int l = 0; l < 3; ++l) { //X
505                     float data = output_ptr[i + 2 * j + 2 * 2 * l + 2 * 2 * 3 * k];
506                     data = (data - shiftf) / scalef;
507                     sum += data;
508                     var += data * data;
509                 }
510             }
511         }
512         sum /= 2 * 3 * 2;
513         var /= 2 * 3 * 2;
514
515         EXPECT_NEAR(sum, 0, 1e-03F);
516         EXPECT_NEAR(var, 1, 1e-03F);
517     }
518 }
519
520 TEST(batch_normalization_gpu, basic_in2x3x2x2_with_var_mean_outputs) {
521         //  Mean   : 3x2x2
522         //  Input  : 2x3x2x2
523         //  Output : 2x3x2x2
524
525         //  Input:
526         //  f0: b0:  1    2  -10   b1:   0    0     -11
527         //  f0: b0:  3    4  -14   b1:   0.5 -0.5   -15  
528         //  f1: b0:  5    6  -12   b1:   1.5  5.2   -13     
529         //  f1: b0:  7    8  -16   b1:   12   9     -17
530         //
531         //  Mean (to be calculated)
532         //  f0: -3.3333
533         //  f1: -0.3583
534         //
535         //  Variance (to be calculated)
536         //  f0: 44.9305
537         //  f1: 107.0624
538         //
539         //  Scale
540         //  f0: 2.0
541         //  f1: 1.0
542         //
543         //  Shift
544         //  f0: 0.0
545         //  f1: 5.0
546
547
548         const auto& engine = get_test_engine();
549
550         auto input = memory::allocate(engine, { data_types::f32, format::yxfb,{ 2, 2, 3, 2 } });
551         auto mean_out = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
552         auto variance_out = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
553         auto scale = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
554         auto shift = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
555         auto inv_variance = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
556
557         float epsilon = 0.0001f;
558
559         topology topology;
560         topology.add(input_layout("input", input.get_layout()));
561         topology.add(data("scale", scale));
562         topology.add(data("shift", shift));
563         topology.add(mutable_data("mean_out", mean_out));
564         topology.add(mutable_data("variance_out", variance_out));
565         topology.add(mutable_data("inv_variance", inv_variance));
566         topology.add(batch_norm("batch_norm", "input", epsilon, "mean_out", "variance_out", "scale", "shift", "inv_variance"));
567
568         set_values(input, {
569                 1.f, 0.f, 5.f, 1.5f,
570                 2.f, 0.f, 6.f, 5.2f,
571                 -10.f, -11.f, -12.f, -13.f,
572                 3.f, 0.5f, 7.f, 12.f,
573                 4.f, -0.5f, 8.f, 9.f,
574                 -14.f, -15.f, -16.f, -17.f
575         });
576
577         set_values(scale, { 2.f, 1.f });
578         set_values(shift, { 0.f, 5.f });
579
580         network network(engine, topology);
581
582         network.set_input_data("input", input);
583
584         auto outputs = network.execute();
585
586         auto output = outputs.at("batch_norm").get_memory();
587         auto output_ptr = output.pointer<float>();
588
589         std::vector<float> mean_ref = { -3.3333f, -0.3583f };
590         std::vector<float> val_ref = { 44.9305f, 107.0624f };
591
592         for (int j = 0; j < 2; ++j) { //F
593                 float sum = 0, var = 0;
594
595                 auto scalep = scale.pointer<float>();
596                 auto shiftp = shift.pointer<float>();
597                 float scalef = scalep[j];
598                 float shiftf = shiftp[j];
599
600                 auto meanp = mean_out.pointer<float>();
601                 auto varp = variance_out.pointer<float>();
602                 float meanf = meanp[j];
603                 float varf = varp[j];
604
605                 for (int i = 0; i < 2; ++i) { //B
606                         for (int k = 0; k < 2; ++k) { //Y
607                                 for (int l = 0; l < 3; ++l) { //X
608                                         float data = output_ptr[i + 2 * j + 2 * 2 * l + 2 * 2 * 3 * k];
609                                         data = (data - shiftf) / scalef;
610                                         sum += data;
611                                         var += data * data;
612                                 }
613                         }
614                 }
615                 sum /= 2 * 3 * 2;
616                 var /= 2 * 3 * 2;
617
618                 EXPECT_NEAR(sum, 0, 1e-03F);
619                 EXPECT_NEAR(var, 1, 1e-03F);
620
621                 EXPECT_NEAR(meanf, mean_ref[j], 1e-03F);
622                 EXPECT_NEAR(varf, val_ref[j], 1e-03F);
623         }
624 }
625
626 TEST(batch_normalization_gpu, basic_in2x3x2x2_with_var_mean_outputs_no_inv_var) {
627     //  Mean   : 3x2x2
628     //  Input  : 2x3x2x2
629     //  Output : 2x3x2x2
630
631     //  Input:
632     //  f0: b0:  1    2  -10   b1:   0    0     -11
633     //  f0: b0:  3    4  -14   b1:   0.5 -0.5   -15  
634     //  f1: b0:  5    6  -12   b1:   1.5  5.2   -13     
635     //  f1: b0:  7    8  -16   b1:   12   9     -17
636     //
637     //  Mean (to be calculated)
638     //  f0: -3.3333
639     //  f1: -0.3583
640     //
641     //  Variance (to be calculated)
642     //  f0: 44.9305
643     //  f1: 107.0624
644     //
645     //  Scale
646     //  f0: 2.0
647     //  f1: 1.0
648     //
649     //  Shift
650     //  f0: 0.0
651     //  f1: 5.0
652
653
654     const auto& engine = get_test_engine();
655
656     auto input = memory::allocate(engine, { data_types::f32, format::yxfb,{ 2, 2, 3, 2 } });
657     auto mean_out = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
658     auto variance_out = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
659     auto scale = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
660     auto shift = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
661
662     float epsilon = 0.0001f;
663
664     topology topology;
665     topology.add(input_layout("input", input.get_layout()));
666     topology.add(data("scale", scale));
667     topology.add(data("shift", shift));
668     topology.add(mutable_data("mean_out", mean_out));
669     topology.add(mutable_data("variance_out", variance_out));
670     topology.add(batch_norm("batch_norm", "input", epsilon, "mean_out", "variance_out", "scale", "shift"));
671
672     set_values(input, {
673         1.f, 0.f, 5.f, 1.5f,
674         2.f, 0.f, 6.f, 5.2f,
675         -10.f, -11.f, -12.f, -13.f,
676         3.f, 0.5f, 7.f, 12.f,
677         4.f, -0.5f, 8.f, 9.f,
678         -14.f, -15.f, -16.f, -17.f
679     });
680
681     set_values(scale, { 2.f, 1.f });
682     set_values(shift, { 0.f, 5.f });
683
684     network network(engine, topology);
685
686     network.set_input_data("input", input);
687
688     auto outputs = network.execute();
689
690     auto output = outputs.at("batch_norm").get_memory();
691     auto output_ptr = output.pointer<float>();
692
693     std::vector<float> mean_ref = { -3.3333f, -0.3583f };
694     std::vector<float> val_ref = { 44.9305f, 107.0624f };
695
696     for (int j = 0; j < 2; ++j) { //F
697         float sum = 0, var = 0;
698
699         auto scalep = scale.pointer<float>();
700         auto shiftp = shift.pointer<float>();
701         float scalef = scalep[j];
702         float shiftf = shiftp[j];
703
704         auto meanp = mean_out.pointer<float>();
705         auto varp = variance_out.pointer<float>();
706         float meanf = meanp[j];
707         float varf = varp[j];
708
709         for (int i = 0; i < 2; ++i) { //B
710             for (int k = 0; k < 2; ++k) { //Y
711                 for (int l = 0; l < 3; ++l) { //X
712                     float data = output_ptr[i + 2 * j + 2 * 2 * l + 2 * 2 * 3 * k];
713                     data = (data - shiftf) / scalef;
714                     sum += data;
715                     var += data * data;
716                 }
717             }
718         }
719         sum /= 2 * 3 * 2;
720         var /= 2 * 3 * 2;
721
722         EXPECT_NEAR(sum, 0, 1e-03F);
723         EXPECT_NEAR(var, 1, 1e-03F);
724
725         EXPECT_NEAR(meanf, mean_ref[j], 1e-03F);
726         EXPECT_NEAR(varf, val_ref[j], 1e-03F);
727     }
728 }
729
730 TEST(batch_normalization_gpu, basic_in2x3x2x2_with_var_mean_outputs_error_out_type) {
731         const auto& engine = get_test_engine();
732
733         auto input = memory::allocate(engine, { data_types::f32, format::yxfb,{ 2, 2, 3, 2 } });
734         auto mean_out = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
735         auto variance_out = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
736         auto scale = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
737         auto shift = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
738         auto inv_variance = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
739
740         float epsilon = 0.0001f;
741
742         topology topology;
743         topology.add(input_layout("input", input.get_layout()));
744         topology.add(data("scale", scale));
745         topology.add(data("shift", shift));
746         topology.add(data("mean_out", mean_out));
747         topology.add(data("variance_out", variance_out));
748         topology.add(data("inv_variance", inv_variance));
749         topology.add(batch_norm("batch_norm", "input", epsilon, "mean_out", "variance_out", "scale", "shift", "inv_variance"));
750
751         EXPECT_ANY_THROW(network(engine, topology));
752 }
753
754 TEST(batch_normalization_gpu, basic_in2x3x2x2_with_var_mean_outputs_error_non_equal_types) {
755     const auto& engine = get_test_engine();
756
757     auto input = memory::allocate(engine, { data_types::f32, format::yxfb,{ 2, 2, 3, 2 } });
758     auto mean_out = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
759     auto variance_out = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
760     auto scale = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
761     auto shift = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
762     auto inv_variance = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
763
764     float epsilon = 0.0001f;
765
766     topology topology;
767     topology.add(input_layout("input", input.get_layout()));
768     topology.add(data("scale", scale));
769     topology.add(data("shift", shift));
770     topology.add(data("mean_out", mean_out));
771     topology.add(mutable_data("variance_out", variance_out));
772     topology.add(mutable_data("inv_variance", inv_variance));
773     topology.add(batch_norm("batch_norm", "input", epsilon, "mean_out", "variance_out", "scale", "shift", "inv_variance"));
774
775     EXPECT_ANY_THROW(network(engine, topology));
776 }
777
778
779 TEST(batch_normalization_gpu, basic_in2x2x3x2_bfyx) {
780     //  Mean   : 3x2x2
781     //  Input  : 2x3x2x2
782     //  Output : 2x3x2x2
783
784     //  Input:
785     //  f0: b0:  1    2  -10   b1:   0    0     -11
786     //  f0: b0:  3    4  -14   b1:   0.5 -0.5   -15  
787     //  f1: b0:  5    6  -12   b1:   1.5  5.2   -13     
788     //  f1: b0:  7    8  -16   b1:   12   9     -17
789     //
790     //  Mean
791     //  f0: -3.3333
792     //  f1: -0.3583
793     //
794     //  Variance
795     //  f0: 44.9305
796     //  f1: 107.0624
797
798
799     const auto& engine = get_test_engine();
800
801     auto input = memory::allocate(engine, { data_types::f32, format::bfyx,{ 2, 2, 3, 2 } });
802     auto mean = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 2, 1, 1 } });
803     auto variance = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 2, 1, 1 } });
804
805     float epsilon = 0.0001f;
806
807     topology topology;
808     topology.add(input_layout("input", input.get_layout()));
809     topology.add(data("mean", mean));
810     topology.add(data("variance", variance));
811     topology.add(batch_norm("batch_norm", "input", "mean", "variance", epsilon));
812
813     set_values(input, {
814         1.f, 2.f, -10.f, 3.f,
815         4.f, -14.f, 5.f, 6.f,
816         -12.f, 7.f, 8.f, -16.f,
817         0.f, 0.f, -11.f, 0.5f,
818         -0.5f, -15.f, 1.5f, 5.2f,
819         -13.f, 12.f, 9.f, -17.f
820     });
821
822     //  f0: b0:  1    2  -10   b1:   0    0     -11
823     //  f0: b0:  3    4  -14   b1:   0.5 -0.5   -15  
824     //  f1: b0:  5    6  -12   b1:   1.5  5.2   -13     
825     //  f1: b0:  7    8  -16   b1:   12   9     -17
826
827     set_values(mean, { -3.3333f, -0.3583f });
828     set_values(variance, { 44.9305f, 107.0624f });
829
830     network network(engine, topology);
831
832     network.set_input_data("input", input);
833
834     auto outputs = network.execute();
835
836     auto output = outputs.at("batch_norm").get_memory();
837     auto output_ptr = output.pointer<float>();
838
839     for (int j = 0; j < 2; ++j) { //F
840         float sum = 0, var = 0;
841         for (int i = 0; i < 2; ++i) { //B
842             for (int k = 0; k < 2; ++k) { //Y
843                 for (int l = 0; l < 3; ++l) { //X
844                     float data = output_ptr[l + k * 3 + j * 2 * 3 + i * 2 * 2 * 3];
845                     sum += data;
846                     var += data * data;
847                 }
848             }
849         }
850         sum /= 2 * 3 * 2;
851         var /= 2 * 3 * 2;
852
853         EXPECT_NEAR(sum, 0, 1e-03F);
854         EXPECT_NEAR(var, 1, 1e-03F);
855     }
856 }
857
858 TEST(batch_normalization_gpu, basic_in2x2x3x2_bfyx_padding) {
859     //  Mean   : 3x2x2
860     //  Input  : 2x3x2x2
861     //  Output : 2x3x2x2
862     //  Input padding : 1x2
863     //  Output padding : 2x1
864
865     //  Input:
866     //  f0: b0:  1    2  -10   b1:   0    0     -11
867     //  f0: b0:  3    4  -14   b1:   0.5 -0.5   -15  
868     //  f1: b0:  5    6  -12   b1:   1.5  5.2   -13     
869     //  f1: b0:  7    8  -16   b1:   12   9     -17
870     //
871     //  Mean
872     //  f0: -3.3333
873     //  f1: -0.3583
874     //
875     //  Variance
876     //  f0: 44.9305
877     //  f1: 107.0624
878
879
880     const auto& engine = get_test_engine();
881
882     auto input = memory::allocate(engine, { data_types::f32, format::bfyx,{ 2, 2, 3, 2 } });
883     auto mean = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 2, 1, 1 } });
884     auto variance = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 2, 1, 1 } });
885
886     float epsilon = 0.0001f;
887
888     topology topology;
889     topology.add(input_layout("input", input.get_layout()));
890     topology.add(data("mean", mean));
891     topology.add(data("variance", variance));
892     topology.add(reorder("reorder", "input", input.get_layout().with_padding({ { 0, 0, 1, 2 }, 0 })));
893     topology.add(batch_norm("batch_norm", "reorder", "mean", "variance", epsilon, padding({ 0, 0, 2, 1 }, 0)));
894
895     set_values(input, {
896         1.f, 2.f, -10.f, 3.f,
897         4.f, -14.f, 5.f, 6.f,
898         -12.f, 7.f, 8.f, -16.f,
899         0.f, 0.f, -11.f, 0.5f,
900         -0.5f, -15.f, 1.5f, 5.2f,
901         -13.f, 12.f, 9.f, -17.f
902     });
903
904     //  f0: b0:  1    2  -10   b1:   0    0     -11
905     //  f0: b0:  3    4  -14   b1:   0.5 -0.5   -15  
906     //  f1: b0:  5    6  -12   b1:   1.5  5.2   -13     
907     //  f1: b0:  7    8  -16   b1:   12   9     -17
908
909     set_values(mean, { -3.3333f, -0.3583f });
910     set_values(variance, { 44.9305f, 107.0624f });
911
912     network network(engine, topology);
913
914     network.set_input_data("input", input);
915
916     auto outputs = network.execute();
917
918     auto output = outputs.at("batch_norm").get_memory();
919     auto output_ptr = output.pointer<float>();
920
921     for (int j = 0; j < 2; ++j) { //F
922         float sum = 0, var = 0;
923         for (int i = 0; i < 2; ++i) { //B
924             for (int k = 0; k < 2; ++k) { //Y
925                 for (int l = 0; l < 3; ++l) { //X
926                     float data = output_ptr[l + 2 + 7 * (k + 1 + 4 * (j + 2 * i))];
927                     sum += data;
928                     var += data * data;
929                 }
930             }
931         }
932         sum /= 2 * 3 * 2;
933         var /= 2 * 3 * 2;
934
935         EXPECT_NEAR(sum, 0, 1e-03F);
936         EXPECT_NEAR(var, 1, 1e-03F);
937     }
938 }
939
940 TEST(batch_normalization_gpu, basic_to_string) {
941     const auto& engine = get_test_engine();
942
943     auto input = memory::allocate(engine, { data_types::f32, format::yxfb,{ 2, 2, 3, 2 } });
944
945     auto mean = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
946     auto variance = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
947
948     auto scale = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
949     auto shift = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
950
951     auto inv_variance = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
952
953     auto mean_out = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
954     auto variance_out = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
955
956     float epsilon = 0.0001f;
957
958     topology topology;
959     topology.add(input_layout("input", input.get_layout()));
960
961     topology.add(data("mean", mean));
962     topology.add(data("variance", variance));
963
964     topology.add(data("scale", scale));
965     topology.add(data("shift", shift));
966
967     topology.add(mutable_data("inv_variance", inv_variance));
968
969     topology.add(mutable_data("mean_out", mean_out));
970     topology.add(mutable_data("variance_out", variance_out));
971
972     topology.add(batch_norm("batch_norm0", "input", "mean", "variance", epsilon));
973     topology.add(batch_norm("batch_norm1", "input", "mean", "variance", "scale", "shift", epsilon));
974     topology.add(batch_norm("batch_norm2", "input", epsilon));
975     topology.add(batch_norm("batch_norm3", "input", epsilon, "inv_variance"));
976     topology.add(batch_norm("batch_norm4", "input", epsilon, "scale", "shift"));
977     topology.add(batch_norm("batch_norm5", "input", epsilon, "scale", "shift", "inv_variance"));
978     topology.add(batch_norm("batch_norm6", "input", epsilon, "mean_out", "variance_out", "scale", "shift" ));
979     topology.add(batch_norm("batch_norm7", "input", epsilon, "mean_out", "variance_out", "scale", "shift", "inv_variance"));
980
981     network network(engine, topology);
982
983     size_t zero_length = 0;
984
985     EXPECT_NE(network.get_primitive_info("batch_norm0").length(), zero_length);
986     EXPECT_NE(network.get_primitive_info("batch_norm1").length(), zero_length);
987     EXPECT_NE(network.get_primitive_info("batch_norm2").length(), zero_length);
988     EXPECT_NE(network.get_primitive_info("batch_norm3").length(), zero_length);
989     EXPECT_NE(network.get_primitive_info("batch_norm4").length(), zero_length);
990     EXPECT_NE(network.get_primitive_info("batch_norm5").length(), zero_length);
991     EXPECT_NE(network.get_primitive_info("batch_norm6").length(), zero_length);
992     EXPECT_NE(network.get_primitive_info("batch_norm7").length(), zero_length);
993 }                                         
994
995
996 TEST(batch_normalization_gpu, basic_in2x3x2x2_yxfb_scale_shift_different_shapes) {
997     const auto& engine = get_test_engine();
998
999     auto input = memory::allocate(engine, { data_types::f32, format::yxfb,{ 2, 2, 3, 2 } });
1000     auto mean = memory::allocate(engine, { data_types::f32, format::yxfb,{ 2, 1, 1, 1 } });
1001     auto variance = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
1002     auto scale = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 1, 2, 1 } });
1003     auto shift = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 1, 1, 2 } });
1004
1005     float epsilon = 0.0001f;
1006
1007     topology topology;
1008     topology.add(input_layout("input", input.get_layout()));
1009     topology.add(data("mean", mean));
1010     topology.add(data("variance", variance));
1011     topology.add(data("scale", scale));
1012     topology.add(data("shift", shift));
1013     topology.add(batch_norm("batch_norm", "input", "mean", "variance", "scale", "shift", epsilon));
1014
1015     set_values(input, {
1016         1.f, 0.f, 5.f, 1.5f,
1017         2.f, 0.f, 6.f, 5.2f,
1018         -10.f, -11.f, -12.f, -13.f,
1019         3.f, 0.5f, 7.f, 12.f,
1020         4.f, -0.5f, 8.f, 9.f,
1021         -14.f, -15.f, -16.f, -17.f
1022     });
1023
1024     set_values(mean, { -3.3333f, -0.3583f });
1025     set_values(variance, { 44.9305f, 107.0624f });
1026     set_values(scale, { 2.f, 1.f });
1027     set_values(shift, { 0.f, 5.f });
1028
1029     network network(engine, topology);
1030
1031     network.set_input_data("input", input);
1032
1033     auto outputs = network.execute();
1034
1035     auto output = outputs.at("batch_norm").get_memory();
1036     auto output_ptr = output.pointer<float>();
1037
1038     for (int j = 0; j < 2; ++j) { //F
1039         float sum = 0, var = 0;
1040
1041         auto scalep = scale.pointer<float>();
1042         auto shiftp = shift.pointer<float>();
1043         float scalef = scalep[j];
1044         float shiftf = shiftp[j];
1045
1046         for (int i = 0; i < 2; ++i) { //B
1047             for (int k = 0; k < 2; ++k) { //Y
1048                 for (int l = 0; l < 3; ++l) { //X
1049                     float data = output_ptr[i + 2 * j + 2 * 2 * l + 2 * 2 * 3 * k];
1050                     data = (data - shiftf) / scalef;
1051                     sum += data;
1052                     var += data * data;
1053                 }
1054             }
1055         }
1056         sum /= 2 * 3 * 2;
1057         var /= 2 * 3 * 2;
1058
1059         EXPECT_NEAR(sum, 0, 1e-03F);
1060         EXPECT_NEAR(var, 1, 1e-03F);
1061     }
1062 }
1063
1064 TEST(batch_normalization_gpu, basic_in2x3x2x2_yxfb_scale_shift_different_shapes_input_layouts) {
1065     const auto& engine = get_test_engine();
1066
1067     auto input = memory::allocate(engine, { data_types::f32, format::yxfb,{ 2, 2, 3, 2 } });
1068     auto mean = memory::allocate(engine, { data_types::f32, format::yxfb,{ 2, 1, 1, 1 } });
1069     auto variance = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
1070     auto scale = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 1, 2, 1 } });
1071     auto shift = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 1, 1, 2 } });
1072
1073     float epsilon = 0.0001f;
1074
1075     topology topology;
1076     topology.add(input_layout("input", input.get_layout()));
1077     topology.add(input_layout("mean", mean.get_layout()));
1078     topology.add(input_layout("variance", variance.get_layout()));
1079     topology.add(input_layout("scale", scale.get_layout()));
1080     topology.add(input_layout("shift", shift.get_layout()));
1081     topology.add(batch_norm("batch_norm", "input", "mean", "variance", "scale", "shift", epsilon));
1082
1083     set_values(input, {
1084         1.f, 0.f, 5.f, 1.5f,
1085         2.f, 0.f, 6.f, 5.2f,
1086         -10.f, -11.f, -12.f, -13.f,
1087         3.f, 0.5f, 7.f, 12.f,
1088         4.f, -0.5f, 8.f, 9.f,
1089         -14.f, -15.f, -16.f, -17.f
1090     });
1091
1092     set_values(mean, { -3.3333f, -0.3583f });
1093     set_values(variance, { 44.9305f, 107.0624f });
1094     set_values(scale, { 2.f, 1.f });
1095     set_values(shift, { 0.f, 5.f });
1096
1097     network network(engine, topology);
1098
1099     network.set_input_data("input", input);
1100     network.set_input_data("mean", mean);
1101     network.set_input_data("variance", variance);
1102     network.set_input_data("scale", scale);
1103     network.set_input_data("shift", shift);
1104
1105     auto outputs = network.execute();
1106
1107     auto output = outputs.at("batch_norm").get_memory();
1108     auto output_ptr = output.pointer<float>();
1109
1110     for (int j = 0; j < 2; ++j) { //F
1111         float sum = 0, var = 0;
1112
1113         auto scalep = scale.pointer<float>();
1114         auto shiftp = shift.pointer<float>();
1115         float scalef = scalep[j];
1116         float shiftf = shiftp[j];
1117
1118         for (int i = 0; i < 2; ++i) { //B
1119             for (int k = 0; k < 2; ++k) { //Y
1120                 for (int l = 0; l < 3; ++l) { //X
1121                     float data = output_ptr[i + 2 * j + 2 * 2 * l + 2 * 2 * 3 * k];
1122                     data = (data - shiftf) / scalef;
1123                     sum += data;
1124                     var += data * data;
1125                 }
1126             }
1127         }
1128         sum /= 2 * 3 * 2;
1129         var /= 2 * 3 * 2;
1130
1131         EXPECT_NEAR(sum, 0, 1e-03F);
1132         EXPECT_NEAR(var, 1, 1e-03F);
1133     }
1134 }
1135
1136 TEST(batch_normalization_gpu, basic_in2x3x2x2_yxfb_with_var_mean_outputs_no_inv_var_different_shapes) {
1137     const auto& engine = get_test_engine();
1138
1139     auto input = memory::allocate(engine, { data_types::f32, format::yxfb,{ 2, 2, 3, 2 } });
1140     auto mean_out = memory::allocate(engine, { data_types::f32, format::yxfb,{ 2, 1, 1, 1 } });
1141     auto variance_out = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 2, 1, 1 } });
1142     auto scale = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 1, 2, 1 } });
1143     auto shift = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 1, 1, 2 } });
1144
1145     float epsilon = 0.0001f;
1146
1147     topology topology;
1148     topology.add(input_layout("input", input.get_layout()));
1149     topology.add(data("scale", scale));
1150     topology.add(data("shift", shift));
1151     topology.add(mutable_data("mean_out", mean_out));
1152     topology.add(mutable_data("variance_out", variance_out));
1153     topology.add(batch_norm("batch_norm", "input", epsilon, "mean_out", "variance_out", "scale", "shift"));
1154
1155     set_values(input, {
1156         1.f, 0.f, 5.f, 1.5f,
1157         2.f, 0.f, 6.f, 5.2f,
1158         -10.f, -11.f, -12.f, -13.f,
1159         3.f, 0.5f, 7.f, 12.f,
1160         4.f, -0.5f, 8.f, 9.f,
1161         -14.f, -15.f, -16.f, -17.f
1162     });
1163
1164     set_values(scale, { 2.f, 1.f });
1165     set_values(shift, { 0.f, 5.f });
1166
1167     network network(engine, topology);
1168
1169     network.set_input_data("input", input);
1170
1171     auto outputs = network.execute();
1172
1173     auto output = outputs.at("batch_norm").get_memory();
1174     auto output_ptr = output.pointer<float>();
1175
1176     std::vector<float> mean_ref = { -3.3333f, -0.3583f };
1177     std::vector<float> val_ref = { 44.9305f, 107.0624f };
1178
1179     for (int j = 0; j < 2; ++j) { //F
1180         float sum = 0, var = 0;
1181
1182         auto scalep = scale.pointer<float>();
1183         auto shiftp = shift.pointer<float>();
1184         float scalef = scalep[j];
1185         float shiftf = shiftp[j];
1186
1187         auto meanp = mean_out.pointer<float>();
1188         auto varp = variance_out.pointer<float>();
1189         float meanf = meanp[j];
1190         float varf = varp[j];
1191
1192         for (int i = 0; i < 2; ++i) { //B
1193             for (int k = 0; k < 2; ++k) { //Y
1194                 for (int l = 0; l < 3; ++l) { //X
1195                     float data = output_ptr[i + 2 * j + 2 * 2 * l + 2 * 2 * 3 * k];
1196                     data = (data - shiftf) / scalef;
1197                     sum += data;
1198                     var += data * data;
1199                 }
1200             }
1201         }
1202         sum /= 2 * 3 * 2;
1203         var /= 2 * 3 * 2;
1204
1205         EXPECT_NEAR(sum, 0, 1e-03F);
1206         EXPECT_NEAR(var, 1, 1e-03F);
1207
1208         EXPECT_NEAR(meanf, mean_ref[j], 1e-03F);
1209         EXPECT_NEAR(varf, val_ref[j], 1e-03F);
1210     }
1211 }
1212
1213 TEST(batch_normalization_gpu, basic_in2x2x3x2_byxf_scale_shift_different_shapes) {
1214     const auto& engine = get_test_engine();
1215
1216     auto input = memory::allocate(engine, { data_types::f32, format::byxf,{ 2, 2, 3, 2 } });
1217     auto mean = memory::allocate(engine, { data_types::f32, format::byxf,{ 2, 1, 1, 1 } });
1218     auto variance = memory::allocate(engine, { data_types::f32, format::byxf,{ 1, 2, 1, 1 } });
1219     auto scale = memory::allocate(engine, { data_types::f32, format::byxf,{ 1, 1, 2, 1 } });
1220     auto shift = memory::allocate(engine, { data_types::f32, format::byxf,{ 1, 1, 1, 2 } });
1221
1222     float epsilon = 0.0001f;
1223
1224     topology topology;
1225     topology.add(input_layout("input", input.get_layout()));
1226     topology.add(data("mean", mean));
1227     topology.add(data("variance", variance));
1228     topology.add(data("scale", scale));
1229     topology.add(data("shift", shift));
1230     topology.add(batch_norm("batch_norm", "input", "mean", "variance", "scale", "shift", epsilon));
1231
1232     set_values(input, {
1233         1.f, 5.f, 2.f, 6.f, -10.f, -12.f, 
1234         3.f, 7.f, 4.f, 8.f, -14.f, -16.f, 
1235         0.f, 1.5f, 0.f, 5.2f, -11.f, -13.f, 
1236         0.5f, 12.f, -0.5f, 9.f, -15.f, -17.f
1237     });
1238
1239     set_values(mean, { -3.3333f, -0.3583f });
1240     set_values(variance, { 44.9305f, 107.0624f });
1241     set_values(scale, { 2.f, 1.f });
1242     set_values(shift, { 0.f, 5.f });
1243
1244     std::vector<float> expected_result{
1245         0.646469f, 0.517855f, 0.795655f, 0.614501f, -0.99458f, -1.12512f, 
1246         0.944842f, 0.711146f, 1.09403f, 0.807792f, -1.59133f, -1.5117f, 
1247         0.497283f, 0.179596f, 0.497283f, 0.537184f, -1.14377f, -1.22176f, 
1248         0.571876f, 1.19437f, 0.42269f, 0.904437f, -1.74051f, -1.60834f
1249     };
1250
1251     network network(engine, topology);
1252
1253     network.set_input_data("input", input);
1254
1255     auto outputs = network.execute();
1256
1257     auto output = outputs.at("batch_norm").get_memory();
1258     auto output_ptr = output.pointer<float>();
1259
1260     for (int j = 0; j < 2; ++j) { //F
1261         float sum = 0, var = 0;
1262
1263         auto scalep = scale.pointer<float>();
1264         auto shiftp = shift.pointer<float>();
1265         float scalef = scalep[j];
1266         float shiftf = shiftp[j];
1267
1268         for (int i = 0; i < 2; ++i) { //B
1269             for (int k = 0; k < 2; ++k) { //Y
1270                 for (int l = 0; l < 3; ++l) { //X
1271                     auto index = 12 * i + 6 * k + 2 * l + j;
1272                     float data = output_ptr[index];
1273                     data = (data - shiftf) / scalef;
1274                     EXPECT_NEAR(data, expected_result[index], 1e-3F);
1275                     sum += data;
1276                     var += data * data;
1277                 }
1278             }
1279         }
1280         sum /= 2 * 3 * 2;
1281         var /= 2 * 3 * 2;
1282
1283         EXPECT_NEAR(sum, 0, 1e-03F);
1284         EXPECT_NEAR(var, 1, 1e-03F);
1285     }
1286 }
1287
1288 TEST(batch_normalization_gpu, basic_in2x2x3x2_byxf_with_var_mean_outputs_no_inv_var_different_shapes) {
1289     const auto& engine = get_test_engine();
1290
1291     auto input = memory::allocate(engine, { data_types::f32, format::byxf,{ 2, 2, 3, 2 } });
1292     auto mean_out = memory::allocate(engine, { data_types::f32, format::byxf,{ 2, 1, 1, 1 } });
1293     auto variance_out = memory::allocate(engine, { data_types::f32, format::byxf,{ 1, 2, 1, 1 } });
1294     auto scale = memory::allocate(engine, { data_types::f32, format::byxf,{ 1, 1, 2, 1 } });
1295     auto shift = memory::allocate(engine, { data_types::f32, format::byxf,{ 1, 1, 1, 2 } });
1296
1297     float epsilon = 0.0001f;
1298
1299     topology topology;
1300     topology.add(input_layout("input", input.get_layout()));
1301     topology.add(data("scale", scale));
1302     topology.add(data("shift", shift));
1303     topology.add(mutable_data("mean_out", mean_out));
1304     topology.add(mutable_data("variance_out", variance_out));
1305     topology.add(batch_norm("batch_norm", "input", epsilon, "mean_out", "variance_out", "scale", "shift"));
1306
1307     set_values(input, {
1308         1.f, 5.f, 2.f, 6.f, -10.f, -12.f,
1309         3.f, 7.f, 4.f, 8.f, -14.f, -16.f,
1310         0.f, 1.5f, 0.f, 5.2f, -11.f, -13.f,
1311         0.5f, 12.f, -0.5f, 9.f, -15.f, -17.f
1312     });
1313
1314     set_values(scale, { 2.f, 1.f });
1315     set_values(shift, { 0.f, 5.f });
1316
1317     network network(engine, topology);
1318
1319     network.set_input_data("input", input);
1320
1321     auto outputs = network.execute();
1322
1323     auto output = outputs.at("batch_norm").get_memory();
1324     auto output_ptr = output.pointer<float>();
1325
1326     std::vector<float> mean_ref = { -3.3333f, -0.3583f };
1327     std::vector<float> val_ref = { 44.9305f, 107.0624f };
1328
1329     std::vector<float> expected_result{
1330         0.646469f, 0.517855f, 0.795655f, 0.614501f, -0.99458f, -1.12512f,
1331         0.944842f, 0.711146f, 1.09403f, 0.807792f, -1.59133f, -1.5117f,
1332         0.497283f, 0.179596f, 0.497283f, 0.537184f, -1.14377f, -1.22176f,
1333         0.571876f, 1.19437f, 0.42269f, 0.904437f, -1.74051f, -1.60834f
1334     };
1335
1336     for (int j = 0; j < 2; ++j) { //F
1337         float sum = 0, var = 0;
1338
1339         auto scalep = scale.pointer<float>();
1340         auto shiftp = shift.pointer<float>();
1341         float scalef = scalep[j];
1342         float shiftf = shiftp[j];
1343
1344         auto meanp = mean_out.pointer<float>();
1345         auto varp = variance_out.pointer<float>();
1346         float meanf = meanp[j];
1347         float varf = varp[j];
1348
1349         for (int i = 0; i < 2; ++i) { //B
1350             for (int k = 0; k < 2; ++k) { //Y
1351                 for (int l = 0; l < 3; ++l) { //X
1352                     auto index = 12 * i + 6 * k + 2 * l + j;
1353                     float data = output_ptr[index];
1354                     data = (data - shiftf) / scalef;
1355                     EXPECT_NEAR(data, expected_result[index], 1e-3F);
1356                     sum += data;
1357                     var += data * data;
1358                 }
1359             }
1360         }
1361         sum /= 2 * 3 * 2;
1362         var /= 2 * 3 * 2;
1363
1364         EXPECT_NEAR(sum, 0, 1e-03F);
1365         EXPECT_NEAR(var, 1, 1e-03F);
1366
1367         EXPECT_NEAR(meanf, mean_ref[j], 1e-03F);
1368         EXPECT_NEAR(varf, val_ref[j], 1e-03F);
1369     }
1370 }
1371
1372
1373 TEST(batch_normalization_gpu, basic_in2x3x5x2_yxfb_scale_shift_different_shapes) {
1374     const auto& engine = get_test_engine();
1375
1376     auto input = memory::allocate(engine, { data_types::f32, format::yxfb,{ 2, 5, 3, 2 } });
1377     auto mean = memory::allocate(engine, { data_types::f32, format::yxfb,{ 5, 1, 1, 1 } });
1378     auto variance = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 5, 1, 1 } });
1379     auto scale = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 1, 5, 1 } });
1380     auto shift = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 1, 1, 5 } });
1381
1382     float epsilon = 0.0001f;
1383
1384     topology topology;
1385     topology.add(input_layout("input", input.get_layout()));
1386     topology.add(data("mean", mean));
1387     topology.add(data("variance", variance));
1388     topology.add(data("scale", scale));
1389     topology.add(data("shift", shift));
1390     topology.add(batch_norm("batch_norm", "input", "mean", "variance", "scale", "shift", epsilon));
1391
1392     set_values(input, {
1393         // y0x0
1394         1.f, 0.f, // f0
1395         5.f, 1.5f, // f1
1396         1.f, 0.f, // f2
1397         5.f, 1.5f, // f3
1398         1.f, 0.f, // f4
1399
1400         // y0x1
1401         2.f, 0.f, 
1402         6.f, 5.2f,
1403         2.f, 0.f,
1404         6.f, 5.2f,
1405         2.f, 0.f,
1406
1407         // y0x2
1408         -10.f, -11.f, 
1409         -12.f, -13.f,
1410         -10.f, -11.f,
1411         -12.f, -13.f,
1412         -10.f, -11.f,
1413
1414         // y1x0
1415         3.f, 0.5f, 
1416         7.f, 12.f,
1417         3.f, 0.5f,
1418         7.f, 12.f,
1419         3.f, 0.5f,
1420
1421         // y1x1
1422         4.f, -0.5f, 
1423         8.f, 9.f,
1424         4.f, -0.5f,
1425         8.f, 9.f,
1426         4.f, -0.5f,
1427
1428         // y1x2
1429         -14.f, -15.f,
1430         -16.f, -17.f,
1431         -14.f, -15.f,
1432         -16.f, -17.f,
1433         - 14.f, -15.f
1434     });
1435
1436     set_values(mean, { -3.3333f, -0.3583f, -3.3333f, -0.3583f, -3.3333f });
1437     set_values(variance, { 44.9305f, 107.0624f, 44.9305f, 107.0624f, 44.9305f });
1438     set_values(scale, { 2.f, 1.f, 3.f, 4.f, 5.f });
1439     set_values(shift, { 0.f, 5.f, -5.f, -15.f, 0.5f });
1440
1441     std::vector<float> expected_result{
1442         0.646469f, 0.497283f, 
1443         0.517855f, 0.179596f, 
1444         0.646469f, 0.497283f, 
1445         0.517855f, 0.179596f, 
1446         0.646469f, 0.497283f, 
1447         
1448         0.795655f, 0.497283f, 
1449         0.614501f, 0.537184f, 
1450         0.795655f, 0.497283f, 
1451         0.614501f, 0.537184f, 
1452         0.795655f, 0.497283f, 
1453         
1454         -0.99458f, -1.14377f, 
1455         -1.12512f, -1.22176f, 
1456         -0.99458f, -1.14377f, 
1457         -1.12512f, -1.22176f, 
1458         -0.99458f, -1.14377f, 
1459         
1460         0.944842f, 0.571876f, 
1461         0.711146f, 1.19437f, 
1462         0.944842f, 0.571876f, 
1463         0.711146f, 1.19437f, 
1464         0.944842f, 0.571876f, 
1465         
1466         1.09403f, 0.42269f, 
1467         0.807792f, 0.904437f, 
1468         1.09403f, 0.42269f, 
1469         0.807792f, 0.904437f, 
1470         1.09403f, 0.42269f, 
1471         
1472         -1.59133f, -1.74051f, 
1473         -1.5117f, -1.60834f, 
1474         -1.59133f, -1.74051f, 
1475         -1.5117f, -1.60834f, 
1476         -1.59133f, -1.74051f
1477     };
1478
1479     network network(engine, topology);
1480
1481     network.set_input_data("input", input);
1482
1483     auto outputs = network.execute();
1484
1485     auto output = outputs.at("batch_norm").get_memory();
1486     auto output_ptr = output.pointer<float>();
1487
1488     for (int j = 0; j < 5; ++j) { //F
1489         float sum = 0, var = 0;
1490
1491         auto scalep = scale.pointer<float>();
1492         auto shiftp = shift.pointer<float>();
1493         float scalef = scalep[j];
1494         float shiftf = shiftp[j];
1495
1496         for (int i = 0; i < 2; ++i) { //B
1497             for (int k = 0; k < 2; ++k) { //Y
1498                 for (int l = 0; l < 3; ++l) { //X
1499                     int index = 30 * k + 10 * l + 2 * j + i;
1500                     float data = output_ptr[index];
1501                     data = (data - shiftf) / scalef;
1502                     EXPECT_NEAR(data, expected_result[index], 1e-3F);
1503                     sum += data;
1504                     var += data * data;
1505                 }
1506             }
1507         }
1508         sum /= 2 * 3 * 2;
1509         var /= 2 * 3 * 2;
1510
1511         EXPECT_NEAR(sum, 0, 1e-03F);
1512         EXPECT_NEAR(var, 1, 1e-03F);
1513     }
1514 }
1515
1516 TEST(batch_normalization_gpu, basic_in2x3x5x2_yxfb_with_var_mean_outputs_no_inv_var_different_shapes) {
1517     const auto& engine = get_test_engine();
1518
1519     auto input = memory::allocate(engine, { data_types::f32, format::yxfb,{ 2, 5, 3, 2 } });
1520     auto mean_out = memory::allocate(engine, { data_types::f32, format::yxfb,{ 5, 1, 1, 1 } });
1521     auto variance_out = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 5, 1, 1 } });
1522     auto scale = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 1, 5, 1 } });
1523     auto shift = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 1, 1, 5 } });
1524
1525     float epsilon = 0.0001f;
1526
1527     topology topology;
1528     topology.add(input_layout("input", input.get_layout()));
1529     topology.add(data("scale", scale));
1530     topology.add(data("shift", shift));
1531     topology.add(mutable_data("mean_out", mean_out));
1532     topology.add(mutable_data("variance_out", variance_out));
1533     topology.add(batch_norm("batch_norm", "input", epsilon, "mean_out", "variance_out", "scale", "shift"));
1534
1535     set_values(input, {
1536         // y0x0
1537         1.f, 0.f, // f0
1538         5.f, 1.5f, // f1
1539         1.f, 0.f, // f2
1540         5.f, 1.5f, // f3
1541         1.f, 0.f, // f4
1542
1543         // y0x1
1544         2.f, 0.f,
1545         6.f, 5.2f,
1546         2.f, 0.f,
1547         6.f, 5.2f,
1548         2.f, 0.f,
1549
1550         // y0x2
1551         -10.f, -11.f,
1552         -12.f, -13.f,
1553         -10.f, -11.f,
1554         -12.f, -13.f,
1555         -10.f, -11.f,
1556
1557         // y1x0
1558         3.f, 0.5f,
1559         7.f, 12.f,
1560         3.f, 0.5f,
1561         7.f, 12.f,
1562         3.f, 0.5f,
1563
1564         // y1x1
1565         4.f, -0.5f,
1566         8.f, 9.f,
1567         4.f, -0.5f,
1568         8.f, 9.f,
1569         4.f, -0.5f,
1570
1571         // y1x2
1572         -14.f, -15.f,
1573         -16.f, -17.f,
1574         -14.f, -15.f,
1575         -16.f, -17.f,
1576         -14.f, -15.f
1577     });
1578
1579     set_values(scale, { 2.f, 1.f, 3.f, 4.f, 5.f });
1580     set_values(shift, { 0.f, 5.f, -5.f, -15.f, 0.5f });
1581
1582     std::vector<float> expected_result{
1583         0.646469f, 0.497283f,
1584         0.517855f, 0.179596f,
1585         0.646469f, 0.497283f,
1586         0.517855f, 0.179596f,
1587         0.646469f, 0.497283f,
1588
1589         0.795655f, 0.497283f,
1590         0.614501f, 0.537184f,
1591         0.795655f, 0.497283f,
1592         0.614501f, 0.537184f,
1593         0.795655f, 0.497283f,
1594
1595         -0.99458f, -1.14377f,
1596         -1.12512f, -1.22176f,
1597         -0.99458f, -1.14377f,
1598         -1.12512f, -1.22176f,
1599         -0.99458f, -1.14377f,
1600
1601         0.944842f, 0.571876f,
1602         0.711146f, 1.19437f,
1603         0.944842f, 0.571876f,
1604         0.711146f, 1.19437f,
1605         0.944842f, 0.571876f,
1606
1607         1.09403f, 0.42269f,
1608         0.807792f, 0.904437f,
1609         1.09403f, 0.42269f,
1610         0.807792f, 0.904437f,
1611         1.09403f, 0.42269f,
1612
1613         -1.59133f, -1.74051f,
1614         -1.5117f, -1.60834f,
1615         -1.59133f, -1.74051f,
1616         -1.5117f, -1.60834f,
1617         -1.59133f, -1.74051f
1618     };
1619
1620     network network(engine, topology);
1621
1622     network.set_input_data("input", input);
1623
1624     auto outputs = network.execute();
1625
1626     auto output = outputs.at("batch_norm").get_memory();
1627     auto output_ptr = output.pointer<float>();
1628
1629     std::vector<float> mean_ref = { -3.3333f, -0.3583f, -3.3333f, -0.3583f, -3.3333f };
1630     std::vector<float> val_ref = { 44.9305f, 107.0624f, 44.9305f, 107.0624f, 44.9305f };
1631
1632     for (int j = 0; j < 5; ++j) { //F
1633         float sum = 0, var = 0;
1634
1635         auto scalep = scale.pointer<float>();
1636         auto shiftp = shift.pointer<float>();
1637         float scalef = scalep[j];
1638         float shiftf = shiftp[j];
1639
1640         auto meanp = mean_out.pointer<float>();
1641         auto varp = variance_out.pointer<float>();
1642         float meanf = meanp[j];
1643         float varf = varp[j];
1644
1645         for (int i = 0; i < 2; ++i) { //B
1646             for (int k = 0; k < 2; ++k) { //Y
1647                 for (int l = 0; l < 3; ++l) { //X
1648                     int index = 30 * k + 10 * l + 2 * j + i;
1649                     float data = output_ptr[index];
1650                     data = (data - shiftf) / scalef;
1651                     EXPECT_NEAR(data, expected_result[index], 1e-3F);
1652                     sum += data;
1653                     var += data * data;
1654                 }
1655             }
1656         }
1657         sum /= 2 * 3 * 2;
1658         var /= 2 * 3 * 2;
1659
1660         EXPECT_NEAR(sum, 0, 1e-03F);
1661         EXPECT_NEAR(var, 1, 1e-03F);
1662
1663         EXPECT_NEAR(meanf, mean_ref[j], 1e-03F);
1664         EXPECT_NEAR(varf, val_ref[j], 1e-03F);
1665     }
1666 }
1667
1668 TEST(batch_normalization_gpu, basic_in2x2x3x5_byxf_scale_shift_different_shapes) {
1669     const auto& engine = get_test_engine();
1670
1671     auto input = memory::allocate(engine, { data_types::f32, format::byxf,{ 2, 5, 3, 2 } });
1672     auto mean = memory::allocate(engine, { data_types::f32, format::byxf,{ 5, 1, 1, 1 } });
1673     auto variance = memory::allocate(engine, { data_types::f32, format::byxf,{ 1, 5, 1, 1 } });
1674     auto scale = memory::allocate(engine, { data_types::f32, format::byxf,{ 1, 1, 5, 1 } });
1675     auto shift = memory::allocate(engine, { data_types::f32, format::byxf,{ 1, 1, 1, 5 } });
1676
1677     float epsilon = 0.0001f;
1678
1679     topology topology;
1680     topology.add(input_layout("input", input.get_layout()));
1681     topology.add(data("mean", mean));
1682     topology.add(data("variance", variance));
1683     topology.add(data("scale", scale));
1684     topology.add(data("shift", shift));
1685     topology.add(batch_norm("batch_norm", "input", "mean", "variance", "scale", "shift", epsilon));
1686
1687     set_values(input, {
1688         // b0y0
1689         1.f, 5.f, 1.f, 5.f, 1.f, // x0
1690         2.f, 6.f, 2.f, 6.f, 2.f, // x1
1691         -10.f, -12.f, -10.f, -12.f, -10.f, //x2
1692
1693         // b0y1
1694         3.f, 7.f, 3.f, 7.f, 3.f,
1695         4.f, 8.f, 4.f, 8.f, 4.f,
1696         -14.f, -16.f, -14.f, -16.f, -14.f,
1697         
1698         // b1y0
1699         0.f, 1.5f, 0.f, 1.5f, 0.f,
1700         0.f, 5.2f, 0.f, 5.2f, 0.f,
1701         -11.f, -13.f, -11.f, -13.f, -11.f,
1702         
1703         // b1y1
1704         0.5f, 12.f, 0.5f, 12.f, 0.5f,
1705         -0.5f, 9.f, -0.5f, 9.f, -0.5f,
1706         -15.f, -17.f, -15.f, -17.f, -15.f
1707     });
1708
1709     set_values(mean, { -3.3333f, -0.3583f, -3.3333f, -0.3583f, -3.3333f });
1710     set_values(variance, { 44.9305f, 107.0624f, 44.9305f, 107.0624f, 44.9305f });
1711     set_values(scale, { 2.f, 1.f, 3.f, 4.f, 5.f });
1712     set_values(shift, { 0.f, 5.f, -5.f, -15.f, 0.5f });
1713
1714     std::vector<float> expected_result{
1715         0.646469f, 0.517855f, 0.646469f, 0.517855f, 0.646469f,
1716         0.795655f, 0.614501f, 0.795655f, 0.614501f, 0.795655f,
1717         -0.99458f, -1.12512f, -0.99458f, -1.12512f, -0.99458f,
1718
1719         0.944842f, 0.711146f, 0.944842f, 0.711146f, 0.944842f,
1720         1.09403f, 0.807792f, 1.09403f, 0.807792f, 1.09403f,
1721         -1.59133f, -1.5117f, -1.59133f, -1.5117f, -1.59133f,
1722
1723         0.497283f, 0.179596f, 0.497283f, 0.179596f, 0.497283f,
1724         0.497283f, 0.537184f, 0.497283f, 0.537184f, 0.497283f,
1725         -1.14377f, -1.22176f, -1.14377f, -1.22176f, -1.14377f,
1726
1727         0.571876f, 1.19437f, 0.571876f, 1.19437f, 0.571876f,
1728         0.42269f, 0.904437f, 0.42269f, 0.904437f, 0.42269f,
1729         -1.74051f, -1.60834f, -1.74051f, -1.60834f, -1.74051f
1730     };
1731
1732     network network(engine, topology);
1733
1734     network.set_input_data("input", input);
1735
1736     auto outputs = network.execute();
1737
1738     auto output = outputs.at("batch_norm").get_memory();
1739     auto output_ptr = output.pointer<float>();
1740
1741     for (int j = 0; j < 5; ++j) { //F
1742         float sum = 0, var = 0;
1743
1744         auto scalep = scale.pointer<float>();
1745         auto shiftp = shift.pointer<float>();
1746         float scalef = scalep[j];
1747         float shiftf = shiftp[j];
1748
1749         for (int i = 0; i < 2; ++i) { //B
1750             for (int k = 0; k < 2; ++k) { //Y
1751                 for (int l = 0; l < 3; ++l) { //X
1752                     auto index = 30 * i + 15 * k + 5 * l + j;
1753                     float data = output_ptr[index];
1754                     data = (data - shiftf) / scalef;
1755                     EXPECT_NEAR(data, expected_result[index], 1e-3F);
1756                     sum += data;
1757                     var += data * data;
1758                 }
1759             }
1760         }
1761         sum /= 2 * 3 * 2;
1762         var /= 2 * 3 * 2;
1763
1764         EXPECT_NEAR(sum, 0, 1e-03F);
1765         EXPECT_NEAR(var, 1, 1e-03F);
1766     }
1767 }
1768
1769 TEST(batch_normalization_gpu, basic_in2x2x3x5_byxf_with_var_mean_outputs_no_inv_var_different_shapes) {
1770     const auto& engine = get_test_engine();
1771
1772     auto input = memory::allocate(engine, { data_types::f32, format::byxf,{ 2, 5, 3, 2 } });
1773     auto mean_out = memory::allocate(engine, { data_types::f32, format::byxf,{ 5, 1, 1, 1 } });
1774     auto variance_out = memory::allocate(engine, { data_types::f32, format::byxf,{ 1, 5, 1, 1 } });
1775     auto scale = memory::allocate(engine, { data_types::f32, format::byxf,{ 1, 1, 5, 1 } });
1776     auto shift = memory::allocate(engine, { data_types::f32, format::byxf,{ 1, 1, 1, 5 } });
1777
1778     float epsilon = 0.0001f;
1779
1780     topology topology;
1781     topology.add(input_layout("input", input.get_layout()));
1782     topology.add(data("scale", scale));
1783     topology.add(data("shift", shift));
1784     topology.add(mutable_data("mean_out", mean_out));
1785     topology.add(mutable_data("variance_out", variance_out));
1786     topology.add(batch_norm("batch_norm", "input", epsilon, "mean_out", "variance_out", "scale", "shift"));
1787
1788     set_values(input, {
1789         // b0y0
1790         1.f, 5.f, 1.f, 5.f, 1.f, // x0
1791         2.f, 6.f, 2.f, 6.f, 2.f, // x1
1792         -10.f, -12.f, -10.f, -12.f, -10.f, //x2
1793
1794         // b0y1
1795         3.f, 7.f, 3.f, 7.f, 3.f,
1796         4.f, 8.f, 4.f, 8.f, 4.f,
1797         -14.f, -16.f, -14.f, -16.f, -14.f,
1798
1799         // b1y0
1800         0.f, 1.5f, 0.f, 1.5f, 0.f,
1801         0.f, 5.2f, 0.f, 5.2f, 0.f,
1802         -11.f, -13.f, -11.f, -13.f, -11.f,
1803
1804         // b1y1
1805         0.5f, 12.f, 0.5f, 12.f, 0.5f,
1806         -0.5f, 9.f, -0.5f, 9.f, -0.5f,
1807         -15.f, -17.f, -15.f, -17.f, -15.f
1808     });
1809
1810     set_values(scale, { 2.f, 1.f, 3.f, 4.f, 5.f });
1811     set_values(shift, { 0.f, 5.f, -5.f, -15.f, 0.5f });
1812
1813     network network(engine, topology);
1814
1815     network.set_input_data("input", input);
1816
1817     auto outputs = network.execute();
1818
1819     auto output = outputs.at("batch_norm").get_memory();
1820     auto output_ptr = output.pointer<float>();
1821
1822     std::vector<float> mean_ref = { -3.3333f, -0.3583f, -3.3333f, -0.3583f, -3.3333f };
1823     std::vector<float> val_ref = { 44.9305f, 107.0624f, 44.9305f, 107.0624f, 44.9305f };
1824
1825     std::vector<float> expected_result{
1826         0.646469f, 0.517855f, 0.646469f, 0.517855f, 0.646469f,
1827         0.795655f, 0.614501f, 0.795655f, 0.614501f, 0.795655f,
1828         -0.99458f, -1.12512f, -0.99458f, -1.12512f, -0.99458f,
1829
1830         0.944842f, 0.711146f, 0.944842f, 0.711146f, 0.944842f,
1831         1.09403f, 0.807792f, 1.09403f, 0.807792f, 1.09403f,
1832         -1.59133f, -1.5117f, -1.59133f, -1.5117f, -1.59133f,
1833
1834         0.497283f, 0.179596f, 0.497283f, 0.179596f, 0.497283f,
1835         0.497283f, 0.537184f, 0.497283f, 0.537184f, 0.497283f,
1836         -1.14377f, -1.22176f, -1.14377f, -1.22176f, -1.14377f,
1837
1838         0.571876f, 1.19437f, 0.571876f, 1.19437f, 0.571876f,
1839         0.42269f, 0.904437f, 0.42269f, 0.904437f, 0.42269f,
1840         -1.74051f, -1.60834f, -1.74051f, -1.60834f, -1.74051f
1841     };
1842
1843     for (int j = 0; j < 5; ++j) { //F
1844         float sum = 0, var = 0;
1845
1846         auto scalep = scale.pointer<float>();
1847         auto shiftp = shift.pointer<float>();
1848         float scalef = scalep[j];
1849         float shiftf = shiftp[j];
1850
1851         auto meanp = mean_out.pointer<float>();
1852         auto varp = variance_out.pointer<float>();
1853         float meanf = meanp[j];
1854         float varf = varp[j];
1855
1856         for (int i = 0; i < 2; ++i) { //B
1857             for (int k = 0; k < 2; ++k) { //Y
1858                 for (int l = 0; l < 3; ++l) { //X
1859                     auto index = 30 * i + 15 * k + 5 * l + j;
1860                     float data = output_ptr[index];
1861                     data = (data - shiftf) / scalef;
1862                     EXPECT_NEAR(data, expected_result[index], 1e-3F);
1863                     sum += data;
1864                     var += data * data;
1865                 }
1866             }
1867         }
1868         sum /= 2 * 3 * 2;
1869         var /= 2 * 3 * 2;
1870
1871         EXPECT_NEAR(sum, 0, 1e-03F);
1872         EXPECT_NEAR(var, 1, 1e-03F);
1873
1874         EXPECT_NEAR(meanf, mean_ref[j], 1e-03F);
1875         EXPECT_NEAR(varf, val_ref[j], 1e-03F);
1876     }
1877 }
1878
1879
1880 TEST(ngraph_batch_normalization_gpu, batchnorm_fprop_b1c2h2w2)
1881 {
1882     const auto& engine = get_test_engine();
1883
1884     tensor input_shape = { 1, 2, 2, 2 };
1885     auto input = memory::allocate(engine, { data_types::f32, format::bfyx, input_shape });
1886     tensor mean_shape = { feature(2) };
1887     auto mean = memory::allocate(engine, { data_types::f32, format::bfyx, mean_shape });
1888     tensor var_shape = { feature(2) };
1889     auto variance = memory::allocate(engine, { data_types::f32, format::bfyx, var_shape });
1890     tensor gamma_shape = { feature(2) };
1891     auto gamma = memory::allocate(engine, { data_types::f32, format::bfyx, gamma_shape });
1892     tensor beta_shape = { feature(2) };
1893     auto beta = memory::allocate(engine, { data_types::f32, format::bfyx, beta_shape });
1894
1895     float eps = 0.001f;
1896
1897     topology topology;
1898     topology.add(input_layout("input", input.get_layout()));
1899     topology.add(data("gamma", gamma));
1900     topology.add(data("beta", beta));
1901     topology.add(mutable_data("mean", mean));
1902     topology.add(mutable_data("variance", variance));
1903     topology.add(batch_norm("batch_norm", "input", eps, "mean", "variance", "gamma", "beta"));
1904
1905     set_values<float>(input, {
1906         0.54881352f,
1907         0.71518934f,
1908         0.60276335f,
1909         0.54488319f,
1910
1911         0.42365479f,
1912         0.64589411f,
1913         0.4375872f,
1914         0.89177299f
1915     });
1916
1917     set_values<float>(gamma, { 1.f, 1.f });
1918     set_values<float>(beta, { 0.f, 0.f });
1919
1920     std::vector<float> expected_result { 
1921         -0.71498716f,
1922         1.48388731f,
1923         -0.00196938f,
1924         -0.76693159f,
1925
1926         -0.91316032f,
1927         0.23943391f,
1928         -0.84090298f,
1929         1.51462936f 
1930     };
1931
1932     std::vector<float> expected_mean = { 0.602912f, 0.599727f };
1933     std::vector<float> expected_variance = { 0.00472505f, 0.0361782f };
1934
1935     network network(engine, topology);
1936
1937     network.set_input_data("input", input);
1938
1939     auto outputs = network.execute();
1940
1941     auto output = outputs.at("batch_norm").get_memory();
1942     auto output_ptr = output.pointer<float>();
1943
1944     for (int j = 0; j < 2; ++j) { //F
1945         float sum = 0;
1946
1947         auto scalep = gamma.pointer<float>();
1948         auto shiftp = beta.pointer<float>();
1949         float scalef = scalep[j];
1950         float shiftf = shiftp[j];
1951
1952         auto meanp = mean.pointer<float>();
1953         auto varp = variance.pointer<float>();
1954         float meanf = meanp[j];
1955         float varf = varp[j];
1956
1957         for (int k = 0; k < 2; ++k) { //Y
1958             for (int l = 0; l < 2; ++l) { //X
1959                 int index = 4 * j + 2 * k + l;
1960                 float data = output_ptr[index];
1961                 data = (data - shiftf) / scalef;
1962                 EXPECT_NEAR(data, expected_result[index], 1e-5F);
1963                 sum += data;
1964             }
1965         }
1966
1967         sum /= 2 * 2;
1968
1969         EXPECT_NEAR(sum, 0, 1e-5F);
1970
1971         EXPECT_NEAR(meanf, expected_mean[j], 1e-5F);
1972         EXPECT_NEAR(varf, expected_variance[j], 1e-5F);
1973     }
1974 }
1975
1976 TEST(ngraph_batch_normalization_gpu, batchnorm_fprop_b2c2h2w1)
1977 {
1978     const auto& engine = get_test_engine();
1979
1980     tensor input_shape = { 2, 2, 1, 2 };
1981     auto input = memory::allocate(engine, { data_types::f32, format::bfyx, input_shape });
1982     tensor mean_shape = { feature(2) };
1983     auto mean = memory::allocate(engine, { data_types::f32, format::bfyx, mean_shape });
1984     tensor var_shape = { feature(2) };
1985     auto variance = memory::allocate(engine, { data_types::f32, format::bfyx, var_shape });
1986     tensor gamma_shape = { feature(2) };
1987     auto gamma = memory::allocate(engine, { data_types::f32, format::bfyx, gamma_shape });
1988     tensor beta_shape = { feature(2) };
1989     auto beta = memory::allocate(engine, { data_types::f32, format::bfyx, beta_shape });
1990
1991     float eps = 0.001f;
1992
1993     topology topology;
1994     topology.add(input_layout("input", input.get_layout()));
1995     topology.add(data("gamma", gamma));
1996     topology.add(data("beta", beta));
1997     topology.add(mutable_data("mean", mean));
1998     topology.add(mutable_data("variance", variance));
1999     topology.add(batch_norm("batch_norm", "input", eps, "mean", "variance", "gamma", "beta"));
2000
2001
2002     set_values<float>(input, { 
2003         0.54881352f,
2004         0.71518934f,
2005
2006         0.60276335f,
2007         0.54488319f,
2008
2009
2010
2011         0.42365479f,
2012         0.64589411f,
2013
2014         0.4375872f,
2015         0.89177299f
2016     });
2017
2018     set_values<float>(gamma, { 1.f, 1.f });
2019     set_values<float>(beta, { 0.f, 0.f });
2020
2021     std::vector<float> expected_result{
2022         -0.30327f, 
2023         1.1561f, 
2024
2025         -0.0963782f, 
2026         -0.434702f, 
2027         
2028
2029
2030         -1.4011f, 
2031         0.548275f, 
2032
2033         -1.06187f,
2034         1.59295f };
2035
2036     std::vector<float> expected_mean = { 0.583388f, 0.619252f };
2037     std::vector<float> expected_variance = { 0.0119972f, 0.0282681f };
2038     network network(engine, topology);
2039
2040     network.set_input_data("input", input);
2041
2042     auto outputs = network.execute();
2043
2044     auto output = outputs.at("batch_norm").get_memory();
2045     auto output_ptr = output.pointer<float>();
2046
2047     for (int j = 0; j < 2; ++j) { //F
2048         float sum = 0;
2049
2050         auto scalep = gamma.pointer<float>();
2051         auto shiftp = beta.pointer<float>();
2052         float scalef = scalep[j];
2053         float shiftf = shiftp[j];
2054
2055         auto meanp = mean.pointer<float>();
2056         auto varp = variance.pointer<float>();
2057         float meanf = meanp[j];
2058         float varf = varp[j];
2059
2060         for (int k = 0; k < 2; ++k) { //B
2061             for (int l = 0; l < 2; ++l) { //Y
2062                 int index = 4 * k + 2 * j + l;
2063                 float data = output_ptr[index];
2064                 data = (data - shiftf) / scalef;
2065                 EXPECT_NEAR(data, expected_result[index], 1e-5F);
2066                 sum += data;
2067             }
2068         }
2069
2070         sum /= 2 * 2;
2071
2072         EXPECT_NEAR(sum, 0, 1e-5F);
2073
2074         EXPECT_NEAR(meanf, expected_mean[j], 1e-5F);
2075         EXPECT_NEAR(varf, expected_variance[j], 1e-5F);
2076     }
2077 }
2078
2079 TEST(ngraph_batch_normalization_gpu, batchnorm_fprop_inference_b2c2h2w1)
2080 {
2081     const auto& engine = get_test_engine();
2082
2083     tensor input_shape = { 2, 2, 1, 2 };
2084     auto input = memory::allocate(engine, { data_types::f32, format::bfyx, input_shape });
2085     tensor mean_shape = { feature(2) };
2086     auto mean = memory::allocate(engine, { data_types::f32, format::bfyx, mean_shape });
2087     tensor var_shape = { feature(2) };
2088     auto variance = memory::allocate(engine, { data_types::f32, format::bfyx, var_shape });
2089     tensor gamma_shape = { feature(2) };
2090     auto gamma = memory::allocate(engine, { data_types::f32, format::bfyx, gamma_shape });
2091     tensor beta_shape = { feature(2) };
2092     auto beta = memory::allocate(engine, { data_types::f32, format::bfyx, beta_shape });
2093
2094     float eps = 0.001f;
2095
2096     topology topology;
2097     topology.add(input_layout("input", input.get_layout()));
2098     topology.add(data("gamma", gamma));
2099     topology.add(data("beta", beta));
2100     topology.add(data("mean", mean));
2101     topology.add(data("variance", variance));
2102     topology.add(batch_norm("batch_norm", "input", eps, "mean", "variance", "gamma", "beta"));
2103
2104
2105     set_values<float>(input, { 
2106         0.54881352f,
2107         0.71518934f,
2108
2109         0.60276335f,
2110         0.54488319f,
2111
2112
2113
2114         0.42365479f,
2115         0.64589411f,
2116
2117         0.4375872f,
2118         0.89177299f
2119     });
2120
2121     set_values<float>(gamma, { 1.f, 1.f });
2122     set_values<float>(beta, { 0.f, 0.f });
2123
2124     set_values<float>(mean, { 0.583388f, 0.619252f });
2125     set_values<float>(variance, { 0.0119972f, 0.0282681f });
2126
2127     std::vector<float> expected_result{
2128         -0.30327f,
2129         1.1561f,
2130
2131         -0.0963782f,
2132         -0.434702f,
2133         
2134         
2135         -1.4011f,
2136         0.548275f,
2137         
2138         -1.06187f,
2139         1.59295f };
2140
2141     network network(engine, topology);
2142
2143     network.set_input_data("input", input);
2144
2145     auto outputs = network.execute();
2146
2147     auto output = outputs.at("batch_norm").get_memory();
2148     auto output_ptr = output.pointer<float>();
2149
2150     for (int j = 0; j < 2; ++j) { //F
2151         float sum = 0;
2152
2153         auto scalep = gamma.pointer<float>();
2154         auto shiftp = beta.pointer<float>();
2155         float scalef = scalep[j];
2156         float shiftf = shiftp[j];
2157
2158         for (int k = 0; k < 2; ++k) { //B
2159             for (int l = 0; l < 2; ++l) { //Y
2160                 int index = 4 * k + 2 * j + l;
2161                 float data = output_ptr[index];
2162                 data = (data - shiftf) / scalef;
2163                 EXPECT_NEAR(data, expected_result[index], 1e-5F);
2164                 sum += data;
2165             }
2166         }
2167
2168         sum /= 2 * 2;
2169
2170         EXPECT_NEAR(sum, 0, 1e-5F);
2171     }
2172 }
2173
2174 TEST(ngraph_batch_normalization_gpu, batchnorm_fprop_b2c2h2w1_different_shapes)
2175 {
2176     const auto& engine = get_test_engine();
2177
2178     tensor input_shape = { 2, 2, 1, 2 };
2179     auto input = memory::allocate(engine, { data_types::f32, format::bfyx, input_shape });
2180     tensor mean_shape = { 2, 1, 1, 1 };
2181     auto mean = memory::allocate(engine, { data_types::f32, format::bfyx, mean_shape });
2182     tensor var_shape = { 1, 2, 1, 1 };
2183     auto variance = memory::allocate(engine, { data_types::f32, format::bfyx, var_shape });
2184     tensor gamma_shape = { 1, 1, 2, 1 };
2185     auto gamma = memory::allocate(engine, { data_types::f32, format::bfyx, gamma_shape });
2186     tensor beta_shape = { 1, 1, 1, 2 };
2187     auto beta = memory::allocate(engine, { data_types::f32, format::bfyx, beta_shape });
2188
2189     float eps = 0.001f;
2190
2191     topology topology;
2192     topology.add(input_layout("input", input.get_layout()));
2193     topology.add(data("gamma", gamma));
2194     topology.add(data("beta", beta));
2195     topology.add(mutable_data("mean", mean));
2196     topology.add(mutable_data("variance", variance));
2197     topology.add(batch_norm("batch_norm", "input", eps, "mean", "variance", "gamma", "beta"));
2198
2199
2200     set_values<float>(input, {
2201         0.54881352f,
2202         0.71518934f,
2203
2204         0.60276335f,
2205         0.54488319f,
2206
2207
2208
2209         0.42365479f,
2210         0.64589411f,
2211
2212         0.4375872f,
2213         0.89177299f
2214     });
2215
2216     set_values<float>(gamma, { 2.f, 3.f });
2217     set_values<float>(beta, { 5.f, 10.f });
2218
2219     std::vector<float> expected_result{
2220         -0.30327f,
2221         1.1561f,
2222
2223         -0.0963782f,
2224         -0.434702f,
2225
2226
2227
2228         -1.4011f,
2229         0.548275f,
2230
2231         -1.06187f,
2232         1.59295f };
2233
2234     std::vector<float> expected_mean = { 0.583388f, 0.619252f };
2235     std::vector<float> expected_variance = { 0.0119972f, 0.0282681f };
2236     network network(engine, topology);
2237
2238     network.set_input_data("input", input);
2239
2240     auto outputs = network.execute();
2241
2242     auto output = outputs.at("batch_norm").get_memory();
2243     auto output_ptr = output.pointer<float>();
2244
2245     for (int j = 0; j < 2; ++j) { //F
2246         float sum = 0;
2247
2248         auto scalep = gamma.pointer<float>();
2249         auto shiftp = beta.pointer<float>();
2250         float scalef = scalep[j];
2251         float shiftf = shiftp[j];
2252
2253         auto meanp = mean.pointer<float>();
2254         auto varp = variance.pointer<float>();
2255         float meanf = meanp[j];
2256         float varf = varp[j];
2257
2258         for (int k = 0; k < 2; ++k) { //B
2259             for (int l = 0; l < 2; ++l) { //Y
2260                 int index = 4 * k + 2 * j + l;
2261                 float data = output_ptr[index];
2262                 data = (data - shiftf) / scalef;
2263                 EXPECT_NEAR(data, expected_result[index], 1e-5F);
2264                 sum += data;
2265             }
2266         }
2267
2268         sum /= 2 * 2;
2269
2270         EXPECT_NEAR(sum, 0, 1e-5F);
2271
2272         EXPECT_NEAR(meanf, expected_mean[j], 1e-5F);
2273         EXPECT_NEAR(varf, expected_variance[j], 1e-5F);
2274     }
2275 }
2276
2277 TEST(ngraph_batch_normalization_gpu, batchnorm_fprop_inference_b2c2h2w1_different_shapes)
2278 {
2279     const auto& engine = get_test_engine();
2280
2281     tensor input_shape = { 2, 2, 1, 2 };
2282     auto input = memory::allocate(engine, { data_types::f32, format::bfyx, input_shape });
2283     tensor mean_shape = { 2, 1, 1, 1 };
2284     auto mean = memory::allocate(engine, { data_types::f32, format::bfyx, mean_shape });
2285     tensor var_shape = { 1, 1, 2, 1 };
2286     auto variance = memory::allocate(engine, { data_types::f32, format::bfyx, var_shape });
2287     tensor gamma_shape = { 1, 1, 2, 1 };
2288     auto gamma = memory::allocate(engine, { data_types::f32, format::bfyx, gamma_shape });
2289     tensor beta_shape = { 1, 1, 1, 2 };
2290     auto beta = memory::allocate(engine, { data_types::f32, format::bfyx, beta_shape });
2291
2292     float eps = 0.001f;
2293
2294     topology topology;
2295     topology.add(input_layout("input", input.get_layout()));
2296     topology.add(data("gamma", gamma));
2297     topology.add(data("beta", beta));
2298     topology.add(data("mean", mean));
2299     topology.add(data("variance", variance));
2300     topology.add(batch_norm("batch_norm", "input", eps, "mean", "variance", "gamma", "beta"));
2301
2302
2303     set_values<float>(input, {
2304         0.54881352f,
2305         0.71518934f,
2306
2307         0.60276335f,
2308         0.54488319f,
2309
2310
2311
2312         0.42365479f,
2313         0.64589411f,
2314
2315         0.4375872f,
2316         0.89177299f
2317     });
2318
2319     set_values<float>(gamma, { 2.f, 3.f });
2320     set_values<float>(beta, { 5.f, 10.f });
2321
2322     set_values<float>(mean, { 0.583388f, 0.619252f });
2323     set_values<float>(variance, { 0.0119972f, 0.0282681f });
2324
2325     std::vector<float> expected_result{
2326         -0.30327f,
2327         1.1561f,
2328
2329         -0.0963782f,
2330         -0.434702f,
2331
2332
2333         -1.4011f,
2334         0.548275f,
2335
2336         -1.06187f,
2337         1.59295f };
2338
2339     network network(engine, topology);
2340
2341     network.set_input_data("input", input);
2342
2343     auto outputs = network.execute();
2344
2345     auto output = outputs.at("batch_norm").get_memory();
2346     auto output_ptr = output.pointer<float>();
2347
2348     for (int j = 0; j < 2; ++j) { //F
2349         float sum = 0;
2350
2351         auto scalep = gamma.pointer<float>();
2352         auto shiftp = beta.pointer<float>();
2353         float scalef = scalep[j];
2354         float shiftf = shiftp[j];
2355
2356         for (int k = 0; k < 2; ++k) { //B
2357             for (int l = 0; l < 2; ++l) { //Y
2358                 int index = 4 * k + 2 * j + l;
2359                 float data = output_ptr[index];
2360                 data = (data - shiftf) / scalef;
2361                 EXPECT_NEAR(data, expected_result[index], 1e-5F);
2362                 sum += data;
2363             }
2364         }
2365
2366         sum /= 2 * 2;
2367
2368         EXPECT_NEAR(sum, 0, 1e-5F);
2369     }
2370 }
2371
2372 TEST(ngraph_batch_normalization_gpu, batchnorm_fprop_b2c5h2w1_different_shapes)
2373 {
2374     const auto& engine = get_test_engine();
2375
2376     tensor input_shape = { 2, 5, 1, 2 };
2377     auto input = memory::allocate(engine, { data_types::f32, format::bfyx, input_shape });
2378     tensor mean_shape = { 5, 1, 1, 1 };
2379     auto mean = memory::allocate(engine, { data_types::f32, format::bfyx, mean_shape });
2380     tensor var_shape = { 1, 5, 1, 1 };
2381     auto variance = memory::allocate(engine, { data_types::f32, format::bfyx, var_shape });
2382     tensor gamma_shape = { 1, 1, 5, 1 };
2383     auto gamma = memory::allocate(engine, { data_types::f32, format::bfyx, gamma_shape });
2384     tensor beta_shape = { 1, 1, 1, 5 };
2385     auto beta = memory::allocate(engine, { data_types::f32, format::bfyx, beta_shape });
2386
2387     float eps = 0.001f;
2388
2389     topology topology;
2390     topology.add(input_layout("input", input.get_layout()));
2391     topology.add(data("gamma", gamma));
2392     topology.add(data("beta", beta));
2393     topology.add(mutable_data("mean", mean));
2394     topology.add(mutable_data("variance", variance));
2395     topology.add(batch_norm("batch_norm", "input", eps, "mean", "variance", "gamma", "beta"));
2396
2397
2398     set_values<float>(input, {
2399         0.54881352f,
2400         0.71518934f,
2401
2402         0.60276335f,
2403         0.54488319f,
2404
2405         0.54881352f,
2406         0.71518934f,
2407
2408         0.60276335f,
2409         0.54488319f,
2410
2411         0.54881352f,
2412         0.71518934f,
2413
2414
2415
2416         0.42365479f,
2417         0.64589411f,
2418
2419         0.4375872f,
2420         0.89177299f,
2421
2422         0.42365479f,
2423         0.64589411f,
2424
2425         0.4375872f,
2426         0.89177299f,
2427
2428         0.42365479f,
2429         0.64589411f
2430     });
2431
2432     set_values<float>(gamma, { 2.f, 3.f, 4.f, 5.f, 1.f });
2433     set_values<float>(beta, { 5.f, 10.f, -10.f, -15.f, 0.f });
2434
2435     std::vector<float> expected_result{
2436         -0.30327f,
2437         1.1561f,
2438
2439         -0.0963782f,
2440         -0.434702f,
2441
2442         -0.30327f,
2443         1.1561f,
2444
2445         -0.0963782f,
2446         -0.434702f,
2447
2448         -0.30327f,
2449         1.1561f,
2450
2451
2452
2453
2454         -1.4011f,
2455         0.548275f,
2456
2457         -1.06187f,
2458         1.59295f,
2459
2460         -1.4011f,
2461         0.548275f,
2462
2463         -1.06187f,
2464         1.59295f,
2465
2466         -1.4011f,
2467         0.548275f
2468     };
2469
2470     std::vector<float> expected_mean = { 0.583388f, 0.619252f, 0.583388f, 0.619252f, 0.583388f };
2471     std::vector<float> expected_variance = { 0.0119972f, 0.0282681f, 0.0119972f, 0.0282681f, 0.0119972f };
2472     network network(engine, topology);
2473
2474     network.set_input_data("input", input);
2475
2476     auto outputs = network.execute();
2477
2478     auto output = outputs.at("batch_norm").get_memory();
2479     auto output_ptr = output.pointer<float>();
2480
2481     for (int j = 0; j < 5; ++j) { //F
2482         float sum = 0;
2483
2484         auto scalep = gamma.pointer<float>();
2485         auto shiftp = beta.pointer<float>();
2486         float scalef = scalep[j];
2487         float shiftf = shiftp[j];
2488
2489         auto meanp = mean.pointer<float>();
2490         auto varp = variance.pointer<float>();
2491         float meanf = meanp[j];
2492         float varf = varp[j];
2493
2494         for (int k = 0; k < 2; ++k) { //B
2495             for (int l = 0; l < 2; ++l) { //Y
2496                 int index = 10 * k + 2 * j + l;
2497                 float data = output_ptr[index];
2498                 data = (data - shiftf) / scalef;
2499                 EXPECT_NEAR(data, expected_result[index], 1e-5F);
2500                 sum += data;
2501             }
2502         }
2503
2504         sum /= 2 * 2;
2505
2506         EXPECT_NEAR(sum, 0, 1e-5F);
2507
2508         EXPECT_NEAR(meanf, expected_mean[j], 1e-5F);
2509         EXPECT_NEAR(varf, expected_variance[j], 1e-5F);
2510     }
2511 }
2512
2513 TEST(ngraph_batch_normalization_gpu, batchnorm_fprop_inference_b2c5h2w1_different_shapes)
2514 {
2515     const auto& engine = get_test_engine();
2516
2517     tensor input_shape = { 2, 5, 1, 2 };
2518     auto input = memory::allocate(engine, { data_types::f32, format::bfyx, input_shape });
2519     tensor mean_shape = { 5, 1, 1, 1 };
2520     auto mean = memory::allocate(engine, { data_types::f32, format::bfyx, mean_shape });
2521     tensor var_shape = { 1, 5, 1, 1 };
2522     auto variance = memory::allocate(engine, { data_types::f32, format::bfyx, var_shape });
2523     tensor gamma_shape = { 1, 1, 5, 1 };
2524     auto gamma = memory::allocate(engine, { data_types::f32, format::bfyx, gamma_shape });
2525     tensor beta_shape = { 1, 1, 1, 5 };
2526     auto beta = memory::allocate(engine, { data_types::f32, format::bfyx, beta_shape });
2527
2528     float eps = 0.001f;
2529
2530     topology topology;
2531     topology.add(input_layout("input", input.get_layout()));
2532     topology.add(data("gamma", gamma));
2533     topology.add(data("beta", beta));
2534     topology.add(data("mean", mean));
2535     topology.add(data("variance", variance));
2536     topology.add(batch_norm("batch_norm", "input", eps, "mean", "variance", "gamma", "beta"));
2537
2538
2539     set_values<float>(input, {
2540         0.54881352f,
2541         0.71518934f,
2542
2543         0.60276335f,
2544         0.54488319f,
2545
2546         0.54881352f,
2547         0.71518934f,
2548
2549         0.60276335f,
2550         0.54488319f,
2551
2552         0.54881352f,
2553         0.71518934f,
2554
2555
2556
2557         0.42365479f,
2558         0.64589411f,
2559
2560         0.4375872f,
2561         0.89177299f,
2562
2563         0.42365479f,
2564         0.64589411f,
2565
2566         0.4375872f,
2567         0.89177299f,
2568
2569         0.42365479f,
2570         0.64589411f
2571     });
2572
2573     set_values<float>(gamma, { 2.f, 3.f, 4.f, 5.f, 1.f });
2574     set_values<float>(beta, { 5.f, 10.f, -10.f, -15.f, 0.f });
2575
2576     std::vector<float> expected_result{
2577         -0.30327f,
2578         1.1561f,
2579
2580         -0.0963782f,
2581         -0.434702f,
2582
2583         -0.30327f,
2584         1.1561f,
2585
2586         -0.0963782f,
2587         -0.434702f,
2588
2589         -0.30327f,
2590         1.1561f,
2591
2592
2593
2594
2595         -1.4011f,
2596         0.548275f,
2597
2598         -1.06187f,
2599         1.59295f,
2600
2601         -1.4011f,
2602         0.548275f,
2603
2604         -1.06187f,
2605         1.59295f,
2606
2607         -1.4011f,
2608         0.548275f
2609     };
2610
2611     set_values<float>(mean, { 0.583388f, 0.619252f, 0.583388f, 0.619252f, 0.583388f });
2612     set_values<float>(variance, { 0.0119972f, 0.0282681f, 0.0119972f, 0.0282681f, 0.0119972f });
2613     network network(engine, topology);
2614
2615     network.set_input_data("input", input);
2616
2617     auto outputs = network.execute();
2618
2619     auto output = outputs.at("batch_norm").get_memory();
2620     auto output_ptr = output.pointer<float>();
2621
2622     for (int j = 0; j < 5; ++j) { //F
2623         float sum = 0;
2624
2625         auto scalep = gamma.pointer<float>();
2626         auto shiftp = beta.pointer<float>();
2627         float scalef = scalep[j];
2628         float shiftf = shiftp[j];
2629
2630         for (int k = 0; k < 2; ++k) { //B
2631             for (int l = 0; l < 2; ++l) { //Y
2632                 int index = 10 * k + 2 * j + l;
2633                 float data = output_ptr[index];
2634                 data = (data - shiftf) / scalef;
2635                 EXPECT_NEAR(data, expected_result[index], 1e-5F);
2636                 sum += data;
2637             }
2638         }
2639
2640         sum /= 2 * 2;
2641
2642         EXPECT_NEAR(sum, 0, 1e-5F);
2643     }
2644 }
2645
2646 TEST(ngraph_batch_normalization_gpu, batchnorm_fprop_b1c2h2w2_no_bn_output)
2647 {
2648     engine engine;
2649
2650     tensor input_shape = { 1, 2, 2, 2 };
2651     auto input = memory::allocate(engine, { data_types::f32, format::bfyx, input_shape });
2652     tensor mean_shape = { feature(2) };
2653     auto mean = memory::allocate(engine, { data_types::f32, format::bfyx, mean_shape });
2654     tensor var_shape = { feature(2) };
2655     auto variance = memory::allocate(engine, { data_types::f32, format::bfyx, var_shape });
2656     tensor gamma_shape = { feature(2) };
2657     auto gamma = memory::allocate(engine, { data_types::f32, format::bfyx, gamma_shape });
2658     tensor beta_shape = { feature(2) };
2659     auto beta = memory::allocate(engine, { data_types::f32, format::bfyx, beta_shape });
2660
2661     float eps = 0.001f;
2662
2663     topology topology;
2664     topology.add(input_layout("input", input.get_layout()));
2665     topology.add(data("gamma", gamma));
2666     topology.add(data("beta", beta));
2667     topology.add(mutable_data("mean", mean));
2668     topology.add(mutable_data("variance", variance));
2669     topology.add(batch_norm("batch_norm", "input", eps, "mean", "variance", "gamma", "beta"));
2670
2671     set_values<float>(input, {
2672         0.54881352f,
2673         0.71518934f,
2674         0.60276335f,
2675         0.54488319f,
2676
2677         0.42365479f,
2678         0.64589411f,
2679         0.4375872f,
2680         0.89177299f
2681     });
2682
2683     set_values<float>(gamma, { 1.f, 1.f });
2684     set_values<float>(beta, { 0.f, 0.f });
2685
2686     std::vector<float> expected_mean = { 0.602912f, 0.599727f };
2687     std::vector<float> expected_variance = { 0.00472505f, 0.0361782f };
2688
2689     build_options bo;
2690     bo.set_option(build_option::outputs({ "mean", "variance" }));
2691     network network(engine, topology, bo);
2692
2693     network.set_input_data("input", input);
2694
2695     auto outputs = network.execute();
2696
2697     for (int j = 0; j < 2; ++j) { //F
2698         auto meanp = mean.pointer<float>();
2699         auto varp = variance.pointer<float>();
2700         float meanf = meanp[j];
2701         float varf = varp[j];
2702
2703         EXPECT_NEAR(meanf, expected_mean[j], 1e-5F);
2704         EXPECT_NEAR(varf, expected_variance[j], 1e-5F);
2705     }
2706 }