1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
5 #include <gtest/gtest.h>
6 #include <gmock/gmock-spec-builders.h>
7 #include "mkldnn_plugin/mkldnn_graph.h"
9 #include "test_graph.hpp"
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"
17 using namespace InferenceEngine;
18 using namespace ::testing;
20 using namespace mkldnn;
21 using namespace single_layer_tests;
24 struct mvn_test_params {
25 // Formats: NCHW, NCDHW
29 int normalize_variance;
36 vector<std::function<void(MKLDNNPlugin::PrimitiveDescInfo)>> comp;
39 extern InferenceEngine::IExtensionPtr make_FakeExtensions();
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();
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];
59 for (size_t b = 0lu; b < N; b++) {
61 // Calculate mean value
62 if (prm.across_channels) {
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];
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;
91 for (size_t c = 0lu; c < C; c++) {
92 size_t cc = cb + c * C2;
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];
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;
120 if (prm.normalize_variance) {
121 for (size_t b = 0; b < N; b++) {
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);
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;
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);
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;
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">
198 <layer name="mvn" id="2" type="MVN" precision="FP32">
199 <data across_channels="_AC_" normalize_variance="_NV_" eps="_EPS_"/>
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"/>
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");
223 REPLACE_WITH_STR(model, "_FL_", "FakeLayerPLN");
226 for (auto& dim : p.dims) {
227 s_dims += "\n <dim>";
228 s_dims += std::to_string(dim) + "</dim>";
230 REPLACE_WITH_STR(model, "__SRC_DIMS__", s_dims);
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);
236 model = IRTemplateGenerator::getIRTemplate("MVN_Only", p.dims, "FP32", model, edges_t);
242 virtual void TearDown() {
245 virtual void SetUp() {
247 TestsCommon::SetUp();
248 mvn_test_params p = ::testing::WithParamInterface<mvn_test_params>::GetParam();
249 std::string model = getModel(p);
251 CNNNetReader net_reader;
252 ASSERT_NO_THROW(net_reader.ReadNetwork(model.data(), model.length()));
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());
260 MKLDNNGraphTestClass graph;
261 graph.CreateGraph(net_reader.getNetwork(), extMgr);
263 auto& nodes = graph.getNodes();
264 nodes = graph.getNodes();
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));
272 ASSERT_NE(nullptr, node->getSelectedPrimitiveDescriptor());
273 ASSERT_EQ(p.selectedType,
274 node->getSelectedPrimitiveDescriptor()->getImplementationType() & p.selectedType);
277 if (p.isBlockedFormat)
278 ASSERT_EQ(6, nodes.size());
280 ASSERT_EQ(5, nodes.size()); // TODO: should be 4 (redudant reorder in case of both layers are inplace)
282 SizeVector dims_src = p.dims;
285 switch (p.dims.size()) {
294 Blob::Ptr src = make_shared_blob<float, const SizeVector>(Precision::FP32, layout, dims_src);
296 fill_data(src->buffer(), src->size());
298 auto * srcPtr = dynamic_cast<TBlob<float>*>(src.get());
300 if (srcPtr == nullptr)
301 FAIL() << "Cannot cast blob to TBlob<float>.";
304 srcs.insert(std::pair<std::string, Blob::Ptr>("in1", src));
307 out = net_reader.getNetwork().getOutputsInfo();
310 std::pair<std::string, DataPtr> item = *out.begin();
312 TBlob<float>::Ptr output;
313 output = make_shared_blob<float>(item.second->getTensorDesc());
315 outputBlobs[item.first] = output;
317 graph.Infer(srcs, outputBlobs);
319 TBlob<float> dst_ref(item.second->getTensorDesc());
321 ref_mvn(*srcPtr, dst_ref, p);
322 compare(*output, dst_ref, 0.0001f);
323 } catch (const details::InferenceEngineException &e) {
329 TEST_P(MKLDNNCPUExtMVNTests, TestsMVN) {}
331 INSTANTIATE_TEST_CASE_P(
332 TestsMVN, MKLDNNCPUExtMVNTests,
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 },
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 }