Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / tests / unit / engines / mkldnn / graph / layers / extensions / mvn_tests.cpp
1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4
5 #include <gtest/gtest.h>
6 #include <gmock/gmock-spec-builders.h>
7 #include "mkldnn_plugin/mkldnn_graph.h"
8
9 #include "test_graph.hpp"
10
11 #include "single_layer_common.hpp"
12 #include <mkldnn_plugin/mkldnn_extension_utils.h>
13 #include <extension/ext_list.hpp>
14 #include "tests_common.hpp"
15 #include "ir_gen_helper.hpp"
16
17 using namespace InferenceEngine;
18 using namespace ::testing;
19 using namespace std;
20 using namespace mkldnn;
21 using namespace single_layer_tests;
22
23
24 struct mvn_test_params {
25     // Formats: NCHW, NCDHW
26     vector<size_t> dims;
27
28     int across_channels;
29     int normalize_variance;
30     float eps;
31
32     size_t num_prim_desc;
33     bool isBlockedFormat;
34     int selectedType;
35
36     vector<std::function<void(MKLDNNPlugin::PrimitiveDescInfo)>> comp;
37 };
38
39 extern InferenceEngine::IExtensionPtr make_FakeExtensions();
40
41 template <typename data_t>
42 void ref_mvn(const TBlob<data_t> &src, TBlob<data_t> &dst, mvn_test_params prm) {
43     const data_t *src_data = src.readOnly();
44     data_t *dst_data = dst.data();
45     size_t dims_size = prm.dims.size();
46
47     size_t N = prm.dims[0];
48     size_t C = prm.dims[1];
49     size_t D = dims_size > 4 ? prm.dims[dims_size - 3lu] : 1lu;
50     size_t H = dims_size > 3 ? prm.dims[dims_size - 2lu] : 1lu;
51     size_t W = prm.dims[dims_size - 1lu];
52
53     float eps = prm.eps;
54
55     size_t C1 = H * W;
56     size_t C2 = C1 * D;
57     size_t C3 = C2 * C;
58
59     for (size_t b = 0lu; b < N; b++) {
60         size_t cb = b * C3;
61         // Calculate mean value
62         if (prm.across_channels) {
63             double mean = 0.0;
64             for (size_t c = 0lu; c < C; c++) {
65                 size_t cc = cb + c * C2;
66                 for (size_t d = 0lu; d < D; d++) {
67                     size_t cd = cc + d * C1;
68                     for (size_t h = 0lu; h < H; h++) {
69                         size_t ch = cd + h * W;
70                         for (size_t w = 0lu; w < W; w++) {
71                             mean += src_data[ch + w];
72                         }
73                     }
74                 }
75             }
76             mean /= (double)C3;
77             for (size_t c = 0lu; c < C; c++) {
78                 size_t cc = cb + c * C2;
79                 for (size_t d = 0lu; d < D; d++) {
80                     size_t cd = cc + d * C1;
81                     for (size_t h = 0lu; h < H; h++) {
82                         size_t ch = cd + h * W;
83                         for (size_t w = 0lu; w < W; w++) {
84                             size_t index = ch + w;
85                             dst_data[index] = src_data[index] - mean;
86                         }
87                     }
88                 }
89             }
90         } else {
91             for (size_t c = 0lu; c < C; c++) {
92                 size_t cc = cb + c * C2;
93                 double mean = 0.0;
94                 for (size_t d = 0lu; d < D; d++) {
95                     size_t cd = cc + d * C1;
96                     for (size_t h = 0lu; h < H; h++) {
97                         size_t ch = cd + h * W;
98                         for (size_t w = 0lu; w < W; w++) {
99                             mean += src_data[ch + w];
100                         }
101                     }
102                 }
103
104                 mean /= (double)C2;
105
106                 for (size_t d = 0lu; d < D; d++) {
107                     size_t cd = cc + d * C1;
108                     for (size_t h = 0lu; h < H; h++) {
109                         size_t ch = cd + h * W;
110                         for (size_t w = 0lu; w < W; w++) {
111                             size_t index = ch + w;
112                             dst_data[index] = src_data[index] - mean;
113                         }
114                     }
115                 }
116             }
117         }
118     }
119
120     if (prm.normalize_variance) {
121         for (size_t b = 0; b < N; b++) {
122             size_t cb = b * C3;
123             // Calculate variances value
124             if (prm.across_channels) {
125                 double variance = 0.f;
126                 for (size_t c = 0lu; c < C; c++) {
127                     size_t cc = cb + c * C2;
128                     for (size_t d = 0lu; d < D; d++) {
129                         size_t cd = cc + d * C1;
130                         for (size_t h = 0lu; h < H; h++) {
131                             size_t ch = cd + h * W;
132                             for (size_t w = 0lu; w < W; w++) {
133                                 variance += std::pow(dst_data[ch + w], 2);
134                             }
135                         }
136                     }
137                 }
138                 variance /= C3;
139                 variance += eps;
140                 variance = std::pow(variance, 0.5f);
141                 for (size_t c = 0lu; c < C; c++) {
142                     size_t cc = cb + c * C2;
143                     for (size_t d = 0lu; d < D; d++) {
144                         size_t cd = cc + d * C1;
145                         for (size_t h = 0lu; h < H; h++) {
146                             size_t ch = cd + h * W;
147                             for (size_t w = 0lu; w < W; w++) {
148                                 dst_data[ch + w] /= variance;
149                             }
150                         }
151                     }
152                 }
153             } else {
154                 for (size_t c = 0lu; c < C; c++) {
155                     size_t cc = cb + c * C2;
156                     double variance = 0.0;
157                     for (size_t d = 0lu; d < D; d++) {
158                         size_t cd = cc + d * C1;
159                         for (size_t h = 0lu; h < H; h++) {
160                             size_t ch = cd + h * W;
161                             for (size_t w = 0lu; w < W; w++) {
162                                 variance += std::pow(dst_data[ch + w], 2);
163                             }
164                         }
165                     }
166                     variance /= C2;
167                     variance += eps;
168                     variance = std::pow(variance, 0.5f);
169                     for (size_t d = 0lu; d < D; d++) {
170                         size_t cd = cc + d * C1;
171                         for (size_t h = 0lu; h < H; h++) {
172                             size_t ch = cd + h * W;
173                             for (size_t w = 0lu; w < W; w++) {
174                                 dst_data[ch + w] /= variance;
175                             }
176                         }
177                     }
178                 }
179             }
180         }
181     }
182 }
183
184 class MKLDNNCPUExtMVNTests: public TestsCommon, public WithParamInterface<mvn_test_params> {
185     std::string layers_t = R"V0G0N(
186         <layer name="fakeLayer" id="1" type="_FL_" precision="FP32">
187             <input>
188                 <port id="1">
189                     __SRC_DIMS__
190                 </port>
191             </input>
192             <output>
193                 <port id="2">
194                     __SRC_DIMS__
195                 </port>
196             </output>
197         </layer>
198         <layer name="mvn" id="2" type="MVN" precision="FP32">
199             <data across_channels="_AC_" normalize_variance="_NV_" eps="_EPS_"/>
200             <input>
201                 <port id="3">
202                     __SRC_DIMS__
203                 </port>
204             </input>
205             <output>
206                 <port id="4">
207                     __SRC_DIMS__
208                 </port>
209             </output>
210         </layer>
211 )V0G0N";
212
213     std::string edges_t = R"V0G0N(
214         <edge from-layer="0" from-port="0" to-layer="1" to-port="1"/>
215         <edge from-layer="1" from-port="2" to-layer="2" to-port="3"/>
216 )V0G0N";
217
218     std::string getModel(mvn_test_params p) {
219         std::string model = layers_t;
220         if (p.isBlockedFormat)
221             REPLACE_WITH_STR(model, "_FL_", "FakeLayerBLK");
222         else
223             REPLACE_WITH_STR(model, "_FL_", "FakeLayerPLN");
224
225         std::string s_dims;
226         for (auto& dim : p.dims) {
227             s_dims += "\n                    <dim>";
228             s_dims += std::to_string(dim) + "</dim>";
229         }
230         REPLACE_WITH_STR(model, "__SRC_DIMS__", s_dims);
231
232         REPLACE_WITH_NUM(model, "_AC_", p.across_channels);
233         REPLACE_WITH_NUM(model, "_NV_", p.normalize_variance);
234         REPLACE_WITH_NUM(model, "_EPS_", p.eps);
235
236         model = IRTemplateGenerator::getIRTemplate("MVN_Only", p.dims, "FP32", model, edges_t);
237
238         return model;
239     }
240
241 protected:
242     virtual void TearDown() {
243     }
244
245     virtual void SetUp() {
246         try {
247             TestsCommon::SetUp();
248             mvn_test_params p = ::testing::WithParamInterface<mvn_test_params>::GetParam();
249             std::string model = getModel(p);
250
251             CNNNetReader net_reader;
252             ASSERT_NO_THROW(net_reader.ReadNetwork(model.data(), model.length()));
253
254             InferenceEngine::Extension cpuExt(make_so_name("cpu_extension"));
255             MKLDNNPlugin::MKLDNNExtensionManager::Ptr extMgr(new MKLDNNPlugin::MKLDNNExtensionManager());
256             extMgr->AddExtension(InferenceEngine::IExtensionPtr(&cpuExt, [](InferenceEngine::IExtension*){}));
257             extMgr->AddExtension(make_FakeExtensions());
258
259
260             MKLDNNGraphTestClass graph;
261             graph.CreateGraph(net_reader.getNetwork(), extMgr);
262
263             auto& nodes = graph.getNodes();
264             nodes = graph.getNodes();
265
266             for (auto &node : nodes) {
267                 if (node->getName() == "mvn") {
268                     ASSERT_EQ(p.num_prim_desc, node->getSupportedPrimitiveDescriptors().size());
269                     for (size_t j = 0; j < p.num_prim_desc && j < p.comp.size(); j++) {
270                         p.comp.at(j)(node->getSupportedPrimitiveDescriptors().at(j));
271                     }
272                     ASSERT_NE(nullptr, node->getSelectedPrimitiveDescriptor());
273                     ASSERT_EQ(p.selectedType,
274                               node->getSelectedPrimitiveDescriptor()->getImplementationType() & p.selectedType);
275                 }
276             }
277             if (p.isBlockedFormat)
278                 ASSERT_EQ(6, nodes.size());
279             else
280                 ASSERT_EQ(5, nodes.size()); // TODO: should be 4 (redudant reorder in case of both layers are inplace)
281
282             SizeVector dims_src = p.dims;
283
284             Layout layout = ANY;
285             switch (p.dims.size()) {
286                 case 4:
287                     layout = NCHW;
288                     break;
289                 case 5:
290                     layout = NCDHW;
291                     break;
292             }
293
294             Blob::Ptr src = make_shared_blob<float, const SizeVector>(Precision::FP32, layout, dims_src);
295             src->allocate();
296             fill_data(src->buffer(), src->size());
297
298             auto * srcPtr = dynamic_cast<TBlob<float>*>(src.get());
299
300             if (srcPtr == nullptr)
301                 FAIL() << "Cannot cast blob to TBlob<float>.";
302
303             BlobMap srcs;
304             srcs.insert(std::pair<std::string, Blob::Ptr>("in1", src));
305
306             OutputsDataMap out;
307             out = net_reader.getNetwork().getOutputsInfo();
308             BlobMap outputBlobs;
309
310             std::pair<std::string, DataPtr> item = *out.begin();
311
312             TBlob<float>::Ptr output;
313             output = make_shared_blob<float>(item.second->getTensorDesc());
314             output->allocate();
315             outputBlobs[item.first] = output;
316
317             graph.Infer(srcs, outputBlobs);
318
319             TBlob<float> dst_ref(item.second->getTensorDesc());
320             dst_ref.allocate();
321             ref_mvn(*srcPtr, dst_ref, p);
322             compare(*output, dst_ref, 0.0001f);
323         } catch (const details::InferenceEngineException &e) {
324             FAIL() << e.what();
325         }
326     }
327 };
328
329 TEST_P(MKLDNNCPUExtMVNTests, TestsMVN) {}
330
331 INSTANTIATE_TEST_CASE_P(
332         TestsMVN, MKLDNNCPUExtMVNTests,
333         ::testing::Values(
334         /*0*/   mvn_test_params{{2, 64, 15, 15}, 0, 0, 0.00001, 2, false, MKLDNNPlugin::impl_desc_type::unknown },
335                 mvn_test_params{{2,  2, 33, 65}, 0, 0, 0.00001, 2, false, MKLDNNPlugin::impl_desc_type::unknown },
336                 mvn_test_params{{2, 64, 15, 15}, 0, 1, 0.00001, 2, false, MKLDNNPlugin::impl_desc_type::unknown },
337                 mvn_test_params{{2,  2, 33, 65}, 0, 1, 0.00001, 2, false, MKLDNNPlugin::impl_desc_type::unknown },
338                 mvn_test_params{{2, 64, 15, 15}, 1, 0, 0.00001, 2, false, MKLDNNPlugin::impl_desc_type::unknown },
339                 mvn_test_params{{2,  2, 33, 65}, 1, 0, 0.00001, 2, false, MKLDNNPlugin::impl_desc_type::unknown },
340                 mvn_test_params{{2, 64, 15, 15}, 1, 1, 0.00001, 2, false, MKLDNNPlugin::impl_desc_type::unknown },
341                 mvn_test_params{{2,  2, 33, 65}, 1, 1, 0.00001, 2, false, MKLDNNPlugin::impl_desc_type::unknown },
342                 mvn_test_params{{2, 64, 15, 15}, 0, 0, 0.00001, 2, true, MKLDNNPlugin::impl_desc_type::unknown },
343         /*9*/   mvn_test_params{{2,  2, 33, 65}, 0, 0, 0.00001, 2, true, MKLDNNPlugin::impl_desc_type::unknown },
344                 mvn_test_params{{2, 64, 15, 15}, 0, 1, 0.00001, 2, true, MKLDNNPlugin::impl_desc_type::unknown },
345                 mvn_test_params{{2,  2, 33, 65}, 0, 1, 0.00001, 2, true, MKLDNNPlugin::impl_desc_type::unknown },
346                 mvn_test_params{{2, 64, 15, 15}, 1, 0, 0.00001, 2, true, MKLDNNPlugin::impl_desc_type::unknown },
347                 mvn_test_params{{2,  2, 33, 65}, 1, 0, 0.00001, 2, true, MKLDNNPlugin::impl_desc_type::unknown },
348         /*14*/  mvn_test_params{{2,640, 15, 15}, 1, 1, 0.00001, 2, true, MKLDNNPlugin::impl_desc_type::unknown },
349                 mvn_test_params{{2,  2, 33, 65}, 1, 1, 0.00001, 2, true, MKLDNNPlugin::impl_desc_type::unknown },
350
351                 // 5D
352         /*16*/  mvn_test_params{{2, 64, 24, 32, 40}, 0, 0, 0.00001f, 2, false, MKLDNNPlugin::impl_desc_type::unknown },
353                 mvn_test_params{{2, 64, 24, 32, 40}, 0, 1, 0.00001f, 2, false, MKLDNNPlugin::impl_desc_type::unknown },
354                 mvn_test_params{{2, 64, 24, 32, 40}, 1, 0, 0.00001f, 2, false, MKLDNNPlugin::impl_desc_type::unknown },
355                 mvn_test_params{{2, 64, 24, 32, 40}, 1, 1, 0.00001f, 2, false, MKLDNNPlugin::impl_desc_type::unknown },
356                 mvn_test_params{{2, 64, 24, 32, 40}, 0, 0, 0.00001f, 2, true, MKLDNNPlugin::impl_desc_type::unknown },
357                 mvn_test_params{{2, 64, 24, 32, 40}, 0, 1, 0.00001f, 2, true, MKLDNNPlugin::impl_desc_type::unknown },
358                 mvn_test_params{{2, 64, 24, 32, 40}, 1, 0, 0.00001f, 2, true, MKLDNNPlugin::impl_desc_type::unknown },
359         /*23*/  mvn_test_params{{2, 64, 24, 32, 40}, 1, 1, 0.00001f, 2, true, MKLDNNPlugin::impl_desc_type::unknown },
360                 mvn_test_params{{1, 64, 32, 32, 32}, 0, 1, 0.001f, 2, true, MKLDNNPlugin::impl_desc_type::unknown }
361             ));