Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / tests / unit / graph_tools / graph_copy_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 <inference_engine/graph_tools.hpp>
7 #include "test_assertions.hpp"
8 #include <unordered_set>
9 #include <gmock/gmock-generated-function-mockers.h>
10 #include <gmock/gmock-generated-matchers.h>
11 #include <gmock/gmock-more-actions.h>
12 #include "xml_father.hpp"
13 #include "ie_common.h"
14 #include "graph_test_base.hpp"
15 #include <memory>
16
17 #ifdef ENABLE_GNA
18 # include <gna_plugin/quantization/model_quantizer.hpp>
19 #endif
20
21 using namespace testing;
22 using namespace InferenceEngine;
23 using namespace std;
24 using namespace GraphTest;
25
26
27 class GraphCopyTests : public GraphTestsBase {
28
29 protected:
30     MockCopier mc;
31
32     void SetUp() override {
33         GraphTestsBase::_batchSize = 12;
34         GraphTestsBase::SetUp();
35         CONNECT(1, 2);
36         CONNECT(3, 4);
37         CONNECT(4, 2);
38         CONNECT(3, 5);
39         CONNECT(5, 2);
40
41         EXPECT_CALL(mockNet, getInputsInfo(_)).WillRepeatedly(WithArg<0>(Invoke([&](InputsDataMap &maps) {
42             prepareInputs(maps, 12);
43         })));
44
45         EXPECT_CALL(mockNet, getOutputsInfo(_)).WillRepeatedly(WithArg<0>(Invoke([&](OutputsDataMap &maps) {
46             prepareOutputs(maps);
47         })));
48
49         EXPECT_CALL(mockNet, getTargetDevice()).WillRepeatedly(Return(TargetDevice::eCPU));
50         EXPECT_CALL(mockNet, getPrecision()).WillRepeatedly(Return(Precision::FP16));
51         EXPECT_CALL(mockNet, getBatchSize()).WillRepeatedly(Return(12));
52         EXPECT_CALL(mockNet, getName(_, _)).WillRepeatedly(Invoke([](char *pName, size_t len) {
53             memcpy(pName, "nm", 3);
54         }));
55
56         EXPECT_CALL(mc, copyLayer(_)).WillRepeatedly(Invoke([](CNNLayerPtr ptr) {
57             return ptr;
58         }));
59     }
60 };
61
62 TEST_F(GraphCopyTests, copyNetworkPreserveBasicParams) {
63
64     auto clone = CNNNetCopy<MockCopier>(mockNet, mc);
65
66     //network was copied not just assigned
67     ASSERT_NE(clone.get(), &mockNet);
68     ASSERT_EQ(clone->getTargetDevice(), TargetDevice::eCPU);
69     ASSERT_EQ(clone->getPrecision(), Precision::FP16);
70
71     char name[20];
72     clone->getName(name, sizeof(name));
73     ASSERT_STREQ(name, "nm");
74 }
75
76 TEST_F(GraphCopyTests, canPreserveBatchWhenCopyNetwork) {
77     auto clone = CNNNetCopy<MockCopier>(mockNet, mc);
78     ASSERT_EQ(clone->getBatchSize(), 12);
79 }
80
81
82 TEST_F(GraphCopyTests, canPreserveInputs) {
83     auto clone = CNNNetCopy<MockCopier>(mockNet, mc);
84
85     InputsDataMap inputs, inputsTarget;
86     InputsDataMap heads, headsTarget;
87
88     clone->getInputsInfo(inputs);
89     mockNet.getInputsInfo(inputsTarget);
90     ASSERT_INPUTS_INFO_EQ(inputs, inputsTarget);
91 }
92
93 TEST_F(GraphCopyTests, canPreserveOutputs) {
94
95     auto clone = CNNNetCopy<MockCopier>(mockNet, mc);
96
97     OutputsDataMap outTarget, outSource;
98     clone->getOutputsInfo(outTarget);
99     mockNet.getOutputsInfo(outSource);
100
101     ASSERT_OUTPUTS_INFO_EQ(outSource, outTarget);
102 }
103
104 TEST_F(GraphCopyTests, canPreserveAttributes) {
105     auto clone = CNNNetCopy<MockCopier>(mockNet, mc);
106     ADD_ATTR(1, "id", "r-1-2-3");
107     ADD_ATTR(2, "id", "r-1-2-3");
108
109     CNNNetwork cloned (clone.get());
110     auto idMemOutput = cloned.getLayerByName("1")->GetParamAsString("id");
111     auto idMemInput  = cloned.getLayerByName("2")->GetParamAsString("id");
112
113     ASSERT_STREQ(idMemInput.c_str(), idMemOutput.c_str());
114     ASSERT_STREQ(idMemInput.c_str(), "r-1-2-3");
115 }
116
117 TEST_F(GraphCopyTests, canPreserveGetData) {
118     auto clone = CNNNetCopy<MockCopier>(mockNet, mc);
119
120     ASSERT_NE(clone->getData("1"), nullptr);
121     ASSERT_NE(clone->getData("2"), nullptr);
122     ASSERT_NE(clone->getData("3"), nullptr);
123     ASSERT_NE(clone->getData("4"), nullptr);
124     ASSERT_NE(clone->getData("5"), nullptr);
125 }
126
127 TEST_F(GraphCopyTests, canPreserveTopology) {
128     auto iclone = CNNNetCopy<MockCopier>(mockNet, mc);
129     auto clone = CNNNetwork(iclone);
130
131     ASSERT_EQ(clone.layerCount(), 5);
132
133     EXPECT_CALL(*this, visited(1, 0)).Times(1);
134     EXPECT_CALL(*this, visited(2, 1)).Times(1);
135
136     EXPECT_CALL(*this, visited2(3, 0)).Times(1);
137     EXPECT_CALL(*this, visited2(4, AnyOf(1, 2))).Times(1);
138     EXPECT_CALL(*this, visited2(5, AnyOf(1, 2))).Times(1);
139     EXPECT_CALL(*this, visited2(2, 3)).Times(1);
140
141     int idx = 0;
142     CNNNetBFS(clone.getLayerByName("1"), [&](CNNLayerPtr layer) {
143         visited(ID(layer), idx++);
144     });
145
146     idx = 0;
147     CNNNetBFS(clone.getLayerByName("3"), [&](CNNLayerPtr layer) {
148         visited2(ID(layer), idx++);
149     });
150 }
151
152 #ifdef ENABLE_GNA
153 using namespace GNAPluginNS;
154 struct _FP32_2_FP32  : public GNAPluginNS::details::QuantDescTmpl<float, float, float, float, float> {
155 };
156 using FP32_2_FP32 = GNAPluginNS::details::QuantPair<_FP32_2_FP32 , _FP32_2_FP32 >;
157
158 TEST_F(GraphCopyTests, canQuantizeTopology) {
159
160     auto iclone = ModelQuantizer<FP32_2_FP32>().quantize(mockNet, 1.0f);
161     auto clone = CNNNetwork(iclone);
162
163     CNNNetBFS(clone.getLayerByName("1"), [&](CNNLayerPtr layer) {
164         auto params = getInjectedData<QuantizedLayerParams>(layer);
165         ASSERT_NE(params, nullptr);
166     });
167
168     CNNNetBFS(clone.getLayerByName("3"), [&](CNNLayerPtr layer) {
169         auto params = getInjectedData<QuantizedLayerParams>(layer);
170         ASSERT_NE(params, nullptr);
171     });
172 }
173
174 #endif
175
176 TEST(CNNSpecificGraphCopyTests, copyNetworkWithClampLayer) {
177     CNNNetReader netReader;
178     //define minimal network with Clamp layer
179     const std::string SINGLE_LAYER_MODEL = R"V0G0N(
180     <net name="SingleLayer" version="2" batch="1">
181         <layers>
182                 <layer id="0" name="InputLayer" precision="FP16" type="Input">
183                         <output>
184                                 <port id="0">
185                                         <dim>1</dim>
186                                         <dim>3</dim>
187                                         <dim>224</dim>
188                                         <dim>224</dim>
189                                 </port>
190                         </output>
191                 </layer>
192                 <layer id="1" name="ClampLayer" precision="FP16" type="Clamp">
193                     <data max="6" min="0"/>
194                     <input>
195                             <port id="0">
196                                     <dim>1</dim>
197                                     <dim>3</dim>
198                                     <dim>224</dim>
199                                     <dim>224</dim>
200                             </port>
201                     </input>
202                     <output>
203                             <port id="1">
204                                     <dim>1</dim>
205                                     <dim>3</dim>
206                                     <dim>224</dim>
207                                     <dim>224</dim>
208                             </port>
209                     </output>
210                 </layer>
211         </layers>
212         <edges>
213             <edge from-layer="0" from-port="0" to-layer="1" to-port="0"/>
214         </edges>
215     </net>
216     )V0G0N";
217     ASSERT_NO_THROW(netReader.ReadNetwork(SINGLE_LAYER_MODEL.data(), SINGLE_LAYER_MODEL.length()));
218     ASSERT_TRUE(netReader.isParseSuccess());
219     auto network = netReader.getNetwork();
220
221     //copy the network
222     struct EmptyStruct {};
223     auto visitor = [&](CNNLayerPtr lp) { return injectData<EmptyStruct>(lp); };
224     auto copied_net_ptr = CNNNetCopy(network, visitor);
225     auto copied_net = CNNNetwork(copied_net_ptr.get());
226
227     //check that Clamp layer was properly copied
228     auto layer = std::dynamic_pointer_cast<ClampLayer>(copied_net.getLayerByName("ClampLayer"));
229     ASSERT_NE(layer, nullptr) << "Could not perform dynamic cast from base pointer to Clamp layer pointer. "
230             "Net copy could be incorrect.";
231 }
232
233 TEST(CNNSpecificGraphCopyTests, copyPreprocess) {
234     CNNNetReader netReader;
235     //define minimal network with Clamp layer
236     const std::string SINGLE_LAYER_MODEL = R"V0G0N(
237     <net name="SingleLayer" version="2" batch="1">
238         <layers>
239                 <layer id="0" name="InputLayer" precision="FP16" type="Input">
240                         <output>
241                                 <port id="0">
242                                         <dim>1</dim>
243                                         <dim>3</dim>
244                                         <dim>224</dim>
245                                         <dim>224</dim>
246                                 </port>
247                         </output>
248                 </layer>
249                 <layer id="1" name="ClampLayer" precision="FP16" type="Clamp">
250                     <data max="6" min="0"/>
251                     <input>
252                             <port id="0">
253                                     <dim>1</dim>
254                                     <dim>3</dim>
255                                     <dim>224</dim>
256                                     <dim>224</dim>
257                             </port>
258                     </input>
259                     <output>
260                             <port id="1">
261                                     <dim>1</dim>
262                                     <dim>3</dim>
263                                     <dim>224</dim>
264                                     <dim>224</dim>
265                             </port>
266                     </output>
267                 </layer>
268         </layers>
269         <edges>
270             <edge from-layer="0" from-port="0" to-layer="1" to-port="0"/>
271         </edges>
272         <pre-process reference-layer-name="InputLayer">
273             <channel id="0">
274                 <mean value="104"/>
275             </channel>
276             <channel id="1">
277                 <mean value="116"/>
278             </channel>
279             <channel id="2">
280                 <mean value="122"/>
281             </channel>
282         </pre-process>
283     </net>
284     )V0G0N";
285     ASSERT_NO_THROW(netReader.ReadNetwork(SINGLE_LAYER_MODEL.data(), SINGLE_LAYER_MODEL.length()));
286     ASSERT_TRUE(netReader.isParseSuccess());
287     auto network = netReader.getNetwork();
288
289     //copy the network
290     struct EmptyStruct {};
291     auto visitor = [&](CNNLayerPtr lp) { return injectData<EmptyStruct>(lp); };
292     auto copied_net_ptr = CNNNetCopy(network, visitor);
293     auto copied_net = CNNNetwork(copied_net_ptr.get());
294
295     //check that pre process Info existed in copied network
296     auto &pp = copied_net.getInputsInfo().begin()->second->getPreProcess();
297     ASSERT_EQ(MEAN_VALUE, pp.getMeanVariant());
298     ASSERT_EQ(3, pp.getNumberOfChannels());
299
300
301     ASSERT_FLOAT_EQ(pp[0]->meanValue, 104);
302     ASSERT_FLOAT_EQ(pp[1]->meanValue, 116);
303     ASSERT_FLOAT_EQ(pp[2]->meanValue, 122);
304 }
305
306 TEST(CNNSpecificGraphCopyTests, copyNetworkWithDeconvolution) {
307     CNNNetReader netReader;
308     //define minimal network with deconvolution layer
309     const std::string SINGLE_LAYER_MODEL = R"V0G0N(
310     <net name="SingleLayer" version="2" batch="1">
311         <layers>
312                 <layer id="0" name="InputLayer" precision="FP16" type="Input">
313                         <output>
314                                 <port id="0">
315                                         <dim>1</dim>
316                                         <dim>384</dim>
317                                         <dim>4</dim>
318                                         <dim>2</dim>
319                                 </port>
320                         </output>
321                 </layer>
322             <layer name="upsample_merged" type="Deconvolution" precision="FP16" id="1">
323             <deconvolution_data stride-x="2" stride-y="2" pad-x="1" pad-y="1" kernel-x="4" kernel-y="4" output="384" group="384"/>
324             <input>
325                 <port id="0">
326                     <dim>1</dim>
327                     <dim>384</dim>
328                     <dim>4</dim>
329                     <dim>2</dim>
330                 </port>
331             </input>
332             <output>
333                 <port id="1">
334                     <dim>1</dim>
335                     <dim>384</dim>
336                     <dim>8</dim>
337                     <dim>4</dim>
338                 </port>
339             </output>
340             <weights offset="5517824" size="12288"/>
341         </layer>
342         </layers>
343         <edges>
344             <edge from-layer="0" from-port="0" to-layer="1" to-port="0"/>
345         </edges>
346     </net>
347     )V0G0N";
348     ASSERT_NO_THROW(netReader.ReadNetwork(SINGLE_LAYER_MODEL.data(), SINGLE_LAYER_MODEL.length()));
349     ASSERT_TRUE(netReader.isParseSuccess());
350     auto network = netReader.getNetwork();
351
352     // copy the network
353     struct EmptyStruct {};
354     auto visitor = [&](CNNLayerPtr lp) { return injectData<EmptyStruct>(lp); };
355     auto copied_net_ptr = CNNNetCopy(network, visitor);
356     auto copied_net = CNNNetwork(copied_net_ptr.get());
357
358     // check that Clamp layer was properly copied
359     auto layer = std::dynamic_pointer_cast<DeconvolutionLayer>(copied_net.getLayerByName("upsample_merged"));
360     ASSERT_NE(layer, nullptr) << "Could not perform dynamic cast from base pointer to Deconvolution layer pointer. "
361                                  "Net copy could be incorrect.";
362 }