Publishing R3
[platform/upstream/dldt.git] / inference-engine / tests / unit / engines / mkldnn / graph / layers / internal / graph_fullyconnected_test.cpp
1 // Copyright (C) 2018 Intel Corporation
2 //
3 // SPDX-License-Identifier: Apache-2.0
4 //
5
6 #include <gtest/gtest.h>
7 #include <gmock/gmock-spec-builders.h>
8 #include "mkldnn_plugin/mkldnn_graph.h"
9 #include "mock_mkldnn_primitive.hpp"
10
11 #include "test_graph.hpp"
12
13 #include "single_layer_common.hpp"
14 #include <mkldnn_plugin/mkldnn_extension_utils.h>
15 #include <inference_engine/cnn_network_impl.hpp>
16 #include "tests_common.hpp"
17
18
19 using namespace ::testing;
20 using namespace std;
21 using namespace mkldnn;
22
23 struct fc_test_params {
24     struct {
25         size_t n;
26         size_t c;
27         size_t h;
28         size_t w;
29     } in;
30
31     size_t out_c;
32
33     size_t num_prim_desc;
34
35     int selectedType;
36     std::vector<MKLDNNPlugin::impl_desc_type> preferTypes;
37
38     std::vector<std::function<void(MKLDNNPlugin::PrimitiveDescInfo)>> comp;
39 };
40
41
42 template <typename data_t>
43 void ref_innerproduct(const InferenceEngine::TBlob<data_t> &src, const data_t *weights, const size_t weightsSize,
44                       InferenceEngine::TBlob<data_t> &dst, fc_test_params prm) {
45     size_t IW = src.dims()[3];
46     size_t IH = src.dims()[2];
47     size_t IC = src.dims()[1];
48     size_t IB = src.dims()[0];
49
50     size_t OC = prm.out_c;
51
52     const data_t *src_data = src.readOnly();
53     const data_t *weights_data = weights;
54     const data_t *bias_data = weights_data + IW*IH*IC*OC;
55     data_t *dst_data = dst.data();
56
57     IE_ASSERT( IW*IH*IC*OC + OC == weightsSize);
58     IE_ASSERT( OC == dst.dims()[0]);
59
60     for (size_t n = 0; n < IB; n++) {
61         for (size_t oc = 0; oc < OC; oc++) {
62             dst_data[n*OC + oc] = bias_data[oc];
63             for (size_t ic = 0; ic < IC; ic++) {
64                 for (size_t kh = 0; kh < IH; kh++) {
65                     for (size_t kw = 0; kw < IW; kw++) {
66                         size_t iidx = n * IC * IH * IW + ic * IH * IW + kh * IW + kw;
67                         size_t widx = oc * IC * IH * IW
68                                       + ic * IH * IW + kh * IW + kw;
69
70                         dst_data[n*OC + oc] += src_data[iidx] * weights_data[widx];
71                     }
72                 }
73             }
74         }
75     }
76 }
77
78 class MKLDNNGraphFullyConnectedTests: public TestsCommon,
79                                       public WithParamInterface<fc_test_params> {
80     std::string model_t = R"V0G0N(
81 <Net Name="FullyConnected_Only" version="2" precision="FP32" batch="1">
82     <layers>
83         <layer name="in1" type="Input" precision="FP32" id="0">
84             <output>
85                 <port id="0">
86                     <dim>_IN_</dim>
87                     <dim>_IC_</dim>
88                     <dim>_IH_</dim>
89                     <dim>_IW_</dim>
90                 </port>
91             </output>
92         </layer>
93         <layer name="FullyConnected" id="1" type="InnerProduct" precision="FP32">
94             <fc out-size="_OC_" PrimitivesPriority="_IMPLS_"/>
95
96             <weights offset="0" size="_S1_" />
97             <biases offset="_S1_" size="_S2_" />
98
99             <input>
100                 <port id="1">
101                     <dim>_IN_</dim>
102                     <dim>_IC_</dim>
103                     <dim>_IH_</dim>
104                     <dim>_IW_</dim>
105                 </port>
106             </input>
107             <output>
108                 <port id="2">
109                     <dim>_IN_</dim>
110                     <dim>_OC_</dim>
111                 </port>
112             </output>
113         </layer>
114     </layers>
115     <edges>
116         <edge from-layer="0" from-port="0" to-layer="1" to-port="1"/>
117     </edges>
118 </Net>
119 )V0G0N";
120
121 protected:
122     std::string getModel(fc_test_params p) {
123         std::string model = model_t;
124         REPLACE_WITH_NUM(model, "_IW_", p.in.w);
125         REPLACE_WITH_NUM(model, "_IH_", p.in.h);
126         REPLACE_WITH_NUM(model, "_IC_", p.in.c);
127         REPLACE_WITH_NUM(model, "_IN_", p.in.n);
128
129         REPLACE_WITH_NUM(model, "_OC_", p.out_c);
130
131         size_t w_data_size = (p.in.w * p.in.h * p.in.c * p.out_c )* sizeof(float);
132         size_t b_data_size = p.out_c * sizeof(float);
133         REPLACE_WITH_NUM(model, "_S1_", w_data_size);
134         REPLACE_WITH_NUM(model, "_S2_", b_data_size);
135         std::string impls;
136         for (const auto& preferType : p.preferTypes) {
137             if (!impls.empty())
138                 impls += ",";
139             impls += "cpu:" + MKLDNNGraphTestClass::getStrPrimitiveDescriptorType(preferType);
140         }
141         REPLACE_WITH_STR(model, "_IMPLS_", impls);
142         return model;
143     }
144
145     virtual void TearDown() {
146     }
147
148     virtual void SetUp() {
149         try {
150             TestsCommon::SetUp();
151             fc_test_params p = ::testing::WithParamInterface<fc_test_params>::GetParam();
152             std::string model = getModel(p);
153
154             InferenceEngine::CNNNetReader net_reader;
155             ASSERT_NO_THROW(net_reader.ReadNetwork(model.data(), model.length()));
156
157             InferenceEngine::TBlob<uint8_t> *weights = new InferenceEngine::TBlob<uint8_t>(InferenceEngine::Precision::U8, InferenceEngine::C, {(p.in.w * p.in.h * p.in.c * p.out_c + p.out_c) * sizeof(float)});
158             weights->allocate();
159             fill_data((float *) weights->buffer(), weights->size() / sizeof(float));
160             InferenceEngine::TBlob<uint8_t>::Ptr weights_ptr = InferenceEngine::TBlob<uint8_t>::Ptr(weights);
161
162             net_reader.SetWeights(weights_ptr);
163
164             MKLDNNGraphTestClass graph;
165             graph.CreateGraph(net_reader.getNetwork());
166             auto& nodes = graph.getNodes();
167             for (int i = 0; i < nodes.size(); i++) {
168                 if (nodes[i]->getType() == MKLDNNPlugin::FullyConnected) {
169                     ASSERT_LE(p.num_prim_desc, nodes[i]->getSupportedPrimitiveDescriptors().size());
170                     for (size_t j = 0; j < p.num_prim_desc && j < p.comp.size(); j++) {
171                         p.comp.at(j)(nodes[i]->getSupportedPrimitiveDescriptors().at(j));
172                     }
173                     ASSERT_NE(nullptr, nodes[i]->getSelectedPrimitiveDescriptor());
174                     ASSERT_EQ(p.selectedType, nodes[i]->getSelectedPrimitiveDescriptor()->getImplementationType() & p.selectedType);
175                 }
176             }
177
178             InferenceEngine::SizeVector dims_src = {p.in.n, p.in.c, p.in.h, p.in.w};
179
180             InferenceEngine::Blob::Ptr src = InferenceEngine::make_shared_blob<float, const InferenceEngine::SizeVector>(InferenceEngine::Precision::FP32, InferenceEngine::NCHW, dims_src);
181             src->allocate();
182             fill_data(src->buffer(), src->size());
183
184             InferenceEngine::TBlob<float>* srcPtr = dynamic_cast<InferenceEngine::TBlob<float>*>(src.get());
185
186             if (srcPtr == nullptr)
187                 FAIL() << "Cannot cast blob to TBlob<float>.";
188
189             InferenceEngine::BlobMap srcs;
190             srcs.insert(std::pair<std::string, InferenceEngine::Blob::Ptr>("in1", src));
191
192             InferenceEngine::OutputsDataMap out;
193             out = net_reader.getNetwork().getOutputsInfo();
194             InferenceEngine::BlobMap outputBlobs;
195
196             std::pair<std::string, InferenceEngine::DataPtr> item = *out.begin();
197
198             InferenceEngine::TBlob<float>::Ptr output;
199             output = InferenceEngine::make_shared_blob<float>(item.second->getTensorDesc());
200             output->allocate();
201             outputBlobs[item.first] = output;
202
203             graph.Infer(srcs, outputBlobs);
204
205             InferenceEngine::TBlob<float> dst_ref(item.second->getTensorDesc());
206             dst_ref.allocate();
207
208             ref_innerproduct(*srcPtr, (const float *)weights->buffer(), weights->size() / sizeof(float), dst_ref, p);
209
210             compare(*output, dst_ref, 0.9f);
211         } catch (const InferenceEngine::details::InferenceEngineException &e) {
212             FAIL() << e.what();
213         }
214     }
215 };
216
217 TEST_P(MKLDNNGraphFullyConnectedTests, TestsFullyConnected) {}
218
219
220 INSTANTIATE_TEST_CASE_P(
221         TestsFullyConnected, MKLDNNGraphFullyConnectedTests,
222         ::testing::Values(
223                 fc_test_params{{1, 3, 227, 227}, 96, 6, MKLDNNPlugin::impl_desc_type::gemm },
224                 fc_test_params{{1, 4, 227, 227}, 8, 6, MKLDNNPlugin::impl_desc_type::gemm },
225                 fc_test_params{{1, 4, 227, 227}, 10, 6, MKLDNNPlugin::impl_desc_type::gemm },
226                 fc_test_params{{1, 3, 227, 227}, 96, 6, MKLDNNPlugin::impl_desc_type::ref, {MKLDNNPlugin::impl_desc_type::ref_any}},
227                 fc_test_params{{1, 4, 227, 227}, 8, 6, MKLDNNPlugin::impl_desc_type::ref, {MKLDNNPlugin::impl_desc_type::ref_any}},
228                 fc_test_params{{1, 4, 227, 227}, 10, 6, MKLDNNPlugin::impl_desc_type::ref, {MKLDNNPlugin::impl_desc_type::ref_any}}));
229
230 class MKLDNNGraphDynBatchFullyConnectedTests: public MKLDNNGraphFullyConnectedTests {
231     virtual void SetUp() {
232         try {
233             TestsCommon::SetUp();
234             fc_test_params p = ::testing::WithParamInterface<fc_test_params>::GetParam();
235             std::string model = getModel(p);
236             size_t MB = p.in.n;
237             if (MB < 2)
238                 MB = 2;
239
240             InferenceEngine::CNNNetReader net_reader;
241             ASSERT_NO_THROW(net_reader.ReadNetwork(model.data(), model.length()));
242
243             InferenceEngine::TBlob<uint8_t> *weights = new InferenceEngine::TBlob<uint8_t>(InferenceEngine::Precision::U8, InferenceEngine::C, {(p.in.w * p.in.h * p.in.c * p.out_c + p.out_c) * sizeof(float)});
244             weights->allocate();
245             fill_data((float *) weights->buffer(), weights->size() / sizeof(float));
246             InferenceEngine::TBlob<uint8_t>::Ptr weights_ptr = InferenceEngine::TBlob<uint8_t>::Ptr(weights);
247             net_reader.SetWeights(weights_ptr);
248             InferenceEngine::CNNNetwork network = net_reader.getNetwork();
249             auto implNet = dynamic_cast<InferenceEngine::details::CNNNetworkImpl *>(&((InferenceEngine::ICNNNetwork&)network));
250             ASSERT_NE(nullptr, implNet) << "Failed to cast ICNNNetwork to CNNNetworkImpl";
251             InferenceEngine::ResponseDesc resp;
252             InferenceEngine::StatusCode sts  = implNet->setBatchSizeReshape(MB, &resp);
253             ASSERT_EQ((int)InferenceEngine::StatusCode::OK, sts) << resp.msg;
254
255             MKLDNNGraphTestClass graph;
256             graph.setProperty({{InferenceEngine::PluginConfigParams::KEY_DYN_BATCH_ENABLED, InferenceEngine::PluginConfigParams::YES}});
257             graph.CreateGraph(net_reader.getNetwork());
258
259             InferenceEngine::SizeVector dims_src = {MB, p.in.c, p.in.h, p.in.w};
260
261             InferenceEngine::Blob::Ptr src = InferenceEngine::make_shared_blob<float, const InferenceEngine::SizeVector>(InferenceEngine::Precision::FP32, InferenceEngine::NCHW, dims_src);
262             src->allocate();
263             fill_data(src->buffer(), src->size());
264
265             InferenceEngine::TBlob<float>* srcPtr = dynamic_cast<InferenceEngine::TBlob<float>*>(src.get());
266
267             if (srcPtr == nullptr)
268                 FAIL() << "Cannot cast blob to TBlob<float>.";
269
270             InferenceEngine::BlobMap srcs;
271             srcs.insert(std::pair<std::string, InferenceEngine::Blob::Ptr>("in1", src));
272
273             InferenceEngine::OutputsDataMap out;
274             out = net_reader.getNetwork().getOutputsInfo();
275             InferenceEngine::BlobMap outputBlobs;
276
277             std::pair<std::string, InferenceEngine::DataPtr> item = *out.begin();
278
279             InferenceEngine::TBlob<float>::Ptr output;
280             output = InferenceEngine::make_shared_blob<float>(item.second->getTensorDesc());
281             output->allocate();
282             outputBlobs[item.first] = output;
283
284             auto checkFC = [](const MKLDNNPlugin::MKLDNNNodePtr& node) {
285                 return node->getType() == MKLDNNPlugin::FullyConnected;
286             };
287
288             graph.checkDynBatch(srcs, outputBlobs, MB, MB, checkFC);
289             graph.checkDynBatch(srcs, outputBlobs, 1, MB, checkFC);
290         } catch (const InferenceEngine::details::InferenceEngineException &e) {
291             FAIL() << e.what();
292         }
293     }
294 };
295
296 TEST_P(MKLDNNGraphDynBatchFullyConnectedTests, TestsDynBatchFullyConnected) {}
297
298 INSTANTIATE_TEST_CASE_P(
299         TestsDynBatchFullyConnected, MKLDNNGraphDynBatchFullyConnectedTests,
300         ::testing::Values(
301                 fc_test_params{{1, 3, 227, 227}, 96, 6, MKLDNNPlugin::impl_desc_type::gemm },
302                 fc_test_params{{1, 4, 227, 227}, 8, 6, MKLDNNPlugin::impl_desc_type::gemm },
303                 fc_test_params{{1, 4, 227, 227}, 10, 6, MKLDNNPlugin::impl_desc_type::gemm },
304                 fc_test_params{{1, 3, 227, 227}, 96, 6, MKLDNNPlugin::impl_desc_type::ref, {MKLDNNPlugin::impl_desc_type::ref_any}},
305                 fc_test_params{{1, 4, 227, 227}, 8, 6, MKLDNNPlugin::impl_desc_type::ref, {MKLDNNPlugin::impl_desc_type::ref_any}},
306                 fc_test_params{{1, 4, 227, 227}, 10, 6, MKLDNNPlugin::impl_desc_type::ref, {MKLDNNPlugin::impl_desc_type::ref_any}}));