Merge pull request #129 from asuhov/2019-r1
[platform/upstream/dldt.git] / inference-engine / tests / unit / engines / mkldnn / graph / layers / extensions / reverse_sequence_tests.cpp
1 // Copyright (C) 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
16
17 using namespace ::testing;
18 using namespace std;
19 using namespace mkldnn;
20
21
22 struct reverse_sequence_test_params {
23     std::string inIdxPrecision;
24     InferenceEngine::SizeVector in_out_shape;
25     std::vector<int32_t> seq_lengths;
26     int                  seq_axis;
27     int                  batch_axis;
28     std::vector<float> reference;
29
30     std::vector<std::function<void(MKLDNNPlugin::PrimitiveDescInfo)>> comp;
31 };
32
33 template <typename data_t>
34 void ref_reverse_sequence(
35     InferenceEngine::TBlob<float> &src,
36     InferenceEngine::TBlob<data_t> &seq_lengths,
37     InferenceEngine::TBlob<float> &dst,
38     int seq_axis,
39     int batch_axis
40 ) {
41     size_t i, src_idx;
42     const float *src_data = src.data();
43     InferenceEngine::SizeVector src_dims = src.getTensorDesc().getDims();
44     InferenceEngine::SizeVector srcStrides = src.getTensorDesc().getBlockingDesc().getStrides();
45     const data_t *seq_lengths_data = seq_lengths.data();
46     InferenceEngine::SizeVector seq_lengths_dims = seq_lengths.getTensorDesc().getDims();
47     float* dst_data = dst.data();
48
49     if (seq_axis < 0)
50         seq_axis += src_dims.size();
51
52     if (seq_axis < 0 || seq_axis >= src_dims.size())
53         FAIL() << "Incorrect 'seq_axis' parameters dimensions and axis number!";
54
55     if (batch_axis < 0)
56         batch_axis += src_dims.size();
57
58     if (batch_axis < 0 || batch_axis >= src_dims.size())
59         FAIL() << "Incorrect 'batch_axis' parameters dimensions and axis number!";
60
61     for (i = 0; i < src_dims[batch_axis]; i++) {
62         if (static_cast<int32_t>(seq_lengths_data[i]) > src_dims[seq_axis])
63             FAIL() << "Incorrect input 'seq_lengths' values!";
64     }
65
66     size_t work_amount_dst = srcStrides[0] * src_dims[0];
67     InferenceEngine::SizeVector counters(src_dims.size(), 0);
68     for (size_t iwork = 0; iwork < work_amount_dst; ++iwork) {
69         for (i = 0, src_idx = 0; i < src_dims.size(); ++i) {
70             size_t idx = counters[i];
71             if (i == seq_axis && idx < static_cast<int32_t>(seq_lengths_data[counters[batch_axis]])) {
72                 idx = static_cast<int32_t>(seq_lengths_data[counters[batch_axis]]) - idx - 1;
73             }
74             src_idx += idx * srcStrides[i];
75         }
76
77         dst_data[iwork] = src_data[src_idx];
78
79         for (int j = src_dims.size() - 1; j >= 0; j--) {
80             counters[j] = (counters[j] + 1) % src_dims[j];
81             if (counters[j] != 0) break;
82         }
83     }
84 }
85
86 class MKLDNNCPUExtReverseSequenceTests : public TestsCommon, public WithParamInterface<reverse_sequence_test_params> {
87     std::string model_t = R"V0G0N(
88 <net Name="ReverseSequence_net" version="2" precision="FP32" batch="1">
89     <layers>
90         <layer name="input" type="Input" precision="FP32" id="1">
91             <output>
92                 <port id="1">
93                     _IN_OUT_
94                 </port>
95             </output>
96         </layer>
97         <layer name="seq_lengths" type="Input" precision="_IIDXP_" id="2">
98             <output>
99                 <port id="2">
100                     <dim>_DIM_SIZE_</dim>
101                 </port>
102             </output>
103         </layer>
104         <layer name="output" id="2" type="ReverseSequence" precision="FP32">
105             <data seq_axis="_SA_" batch_axis="_BA_"/>
106             <input>
107                 <port id="1">
108                     _IN_OUT_
109                 </port>
110                 <port id="2">
111                     <dim>_DIM_SIZE_</dim>
112                 </port>
113             </input>
114             <output>
115                 <port id="3">
116                     _IN_OUT_
117                 </port>
118             </output>
119         </layer>
120     </layers>
121     <edges>
122         <edge from-layer="1" from-port="1" to-layer="2" to-port="1"/>
123         <edge from-layer="2" from-port="2" to-layer="2" to-port="2"/>
124     </edges>
125 </net>
126 )V0G0N";
127
128     std::string getModel(reverse_sequence_test_params p) {
129         std::string model = model_t;
130         std::string in_out_shape;
131         for (size_t i = 0; i < p.in_out_shape.size(); i++) {
132             in_out_shape += "<dim>";
133             in_out_shape += std::to_string(p.in_out_shape[i]) + "</dim>\n";
134         }
135         REPLACE_WITH_STR(model, "_IIDXP_", p.inIdxPrecision);
136         REPLACE_WITH_STR(model, "_IN_OUT_", in_out_shape);
137         REPLACE_WITH_NUM(model, "_DIM_SIZE_", p.seq_lengths.size());
138         REPLACE_WITH_NUM(model, "_SA_", p.seq_axis);
139         REPLACE_WITH_NUM(model, "_BA_", p.batch_axis);
140         return model;
141     }
142
143 protected:
144     virtual void TearDown() {
145     }
146
147     virtual void SetUp() {
148         try {
149             TestsCommon::SetUp();
150             reverse_sequence_test_params p = ::testing::WithParamInterface<reverse_sequence_test_params>::GetParam();
151             std::string model = getModel(p);
152             ////std::cout << model;
153             InferenceEngine::CNNNetReader net_reader;
154             ASSERT_NO_THROW(net_reader.ReadNetwork(model.data(), model.length()));
155
156             InferenceEngine::Extension cpuExt(make_so_name("cpu_extension"));
157             MKLDNNPlugin::MKLDNNExtensionManager::Ptr extMgr(new MKLDNNPlugin::MKLDNNExtensionManager());
158             extMgr->AddExtension(InferenceEngine::IExtensionPtr(&cpuExt, [](InferenceEngine::IExtension*){}));
159
160             MKLDNNGraphTestClass graph;
161             graph.CreateGraph(net_reader.getNetwork(), extMgr);
162
163             // Output Data
164             InferenceEngine::OutputsDataMap out;
165             out = net_reader.getNetwork().getOutputsInfo();
166             InferenceEngine::BlobMap outputBlobs;
167
168             std::pair<std::string, InferenceEngine::DataPtr> item = *out.begin();
169
170             InferenceEngine::TBlob<float>::Ptr output;
171             output = InferenceEngine::make_shared_blob<float>(item.second->getTensorDesc());
172             output->allocate();
173             outputBlobs[item.first] = output;
174
175             // Output Reference
176             InferenceEngine::TBlob<float> dst_ref(item.second->getTensorDesc());
177             dst_ref.allocate();
178
179             // Input Data
180             InferenceEngine::Blob::Ptr src;
181             src = InferenceEngine::make_shared_blob<float>({ InferenceEngine::Precision::FP32, p.in_out_shape, InferenceEngine::TensorDesc::getLayoutByDims(p.in_out_shape) });
182             src->allocate();
183             fill_data_dbgval(src->buffer(), src->size());
184             auto * srcPtr = dynamic_cast<InferenceEngine::TBlob<float>*>(src.get());
185             if (srcPtr == nullptr)
186                 FAIL() << "Cannot cast blob to TBlob<float>.";
187
188             InferenceEngine::BlobMap srcs;
189             srcs.insert(std::pair<std::string, InferenceEngine::Blob::Ptr>("input", src));
190
191             InferenceEngine::Blob::Ptr seq_lengthsIdx;
192             InferenceEngine::SizeVector seq_lengths_dim(1, p.seq_lengths.size());
193             if (p.inIdxPrecision == "I32") {
194                 seq_lengthsIdx = InferenceEngine::make_shared_blob<int32_t>({ InferenceEngine::Precision::I32, seq_lengths_dim, InferenceEngine::TensorDesc::getLayoutByDims(seq_lengths_dim) });
195                 seq_lengthsIdx->allocate();
196                 if (p.seq_lengths.size())
197                     memcpy(static_cast<int32_t*>(seq_lengthsIdx->buffer()), &p.seq_lengths[0], sizeof(int32_t)*p.seq_lengths.size());
198                 auto * seq_lengthsIdxPtr = dynamic_cast<InferenceEngine::TBlob<int32_t>*>(seq_lengthsIdx.get());
199                 if (seq_lengthsIdxPtr == nullptr)
200                     FAIL() << "Cannot cast blob to TBlob<int32_t>.";
201
202                 // Check results
203                 ref_reverse_sequence(*srcPtr, *seq_lengthsIdxPtr, dst_ref, p.seq_axis, p.batch_axis);
204                 if (p.reference.size()) {
205                     if (memcmp(dst_ref.data(), &p.reference[0], p.reference.size() * sizeof(float)) != 0)
206                         FAIL() << "Wrong result with compare TF reference!";
207                 }
208                 srcs.insert(std::pair<std::string, InferenceEngine::Blob::Ptr>("seq_lengths", seq_lengthsIdx));
209             } else if (p.inIdxPrecision == "FP32") {
210                 seq_lengthsIdx = InferenceEngine::make_shared_blob<float>({ InferenceEngine::Precision::FP32, seq_lengths_dim, InferenceEngine::TensorDesc::getLayoutByDims(seq_lengths_dim) });
211                 seq_lengthsIdx->allocate();
212                 if (p.seq_lengths.size())
213                     for (size_t i = 0; i < p.seq_lengths.size(); i++) {
214                         static_cast<float *>(seq_lengthsIdx->buffer())[i] = static_cast<float>(p.seq_lengths[i]);
215                     }
216                 auto * seq_lengthsIdxPtr = dynamic_cast<InferenceEngine::TBlob<float>*>(seq_lengthsIdx.get());
217                 if (seq_lengthsIdxPtr == nullptr)
218                     FAIL() << "Cannot cast blob to TBlob<float>.";
219
220                 // Check results
221                 ref_reverse_sequence(*srcPtr, *seq_lengthsIdxPtr, dst_ref, p.seq_axis, p.batch_axis);
222                 if (p.reference.size()) {
223                     if (memcmp(dst_ref.data(), &p.reference[0], p.reference.size() * sizeof(float)) != 0)
224                         FAIL() << "Wrong result with compare TF reference!";
225                 }
226                 srcs.insert(std::pair<std::string, InferenceEngine::Blob::Ptr>("seq_lengths", seq_lengthsIdx));
227             } else {
228                 return;
229             }
230
231             // Infer
232             graph.Infer(srcs, outputBlobs);
233             compare(*output, dst_ref);
234         } catch (const InferenceEngine::details::InferenceEngineException &e) {
235             FAIL() << e.what();
236         }
237     }
238 };
239
240 //  Test data vectors
241 static std::vector<float> test0 = { 9.f,10.f,11.f,12.f,13.f,14.f,15.f,16.f,17.f,0.f,1.f,2.f,3.f,4.f,5.f,6.f,7.f,8.f,18.f,19.f,20.f,21.f,22.f,23.f,24.f,25.f,26.f };
242 static std::vector<float> test2 = { 3.f,4.f,5.f,0.f,1.f,2.f,6.f,7.f,8.f,12.f,13.f,14.f,9.f,10.f,11.f,15.f,16.f,17.f,21.f,22.f,23.f,18.f,19.f,20.f,24.f,25.f,26.f };
243 static std::vector<float> test4 = { 1.f,0.f,2.f,4.f,3.f,5.f,7.f,6.f,8.f,10.f,9.f,11.f,13.f,12.f,14.f,16.f,15.f,17.f,19.f,18.f,20.f,22.f,21.f,23.f,25.f,24.f,26.f };
244 static std::vector<float> test6 = { 2.f,1.f,0.f,4.f,3.f,5.f };
245 static std::vector<float> test7 = { 0.f,1.f,2.f,3.f,4.f,5.f,6.f,7.f,8.f,12.f,13.f,14.f,9.f,10.f,11.f,15.f,16.f,17.f,24.f,25.f,26.f,21.f,22.f,23.f,18.f,19.f,20.f };
246 static std::vector<float> test8 = { 0.f,4.f,8.f,3.f,1.f,5.f,6.f,7.f,2.f,9.f,13.f,17.f,12.f,10.f,14.f,15.f,16.f,11.f,18.f,22.f,26.f,21.f,19.f,23.f,24.f,25.f,20.f };
247
248 TEST_P(MKLDNNCPUExtReverseSequenceTests, TestsReverseSequence) {}
249 INSTANTIATE_TEST_CASE_P(
250     TestsReverseSequence, MKLDNNCPUExtReverseSequenceTests,
251             ::testing::Values(
252 // Params: in_out_shape, seq_lengths, seq_axis, batch_axis, reference
253 /*  0 */        reverse_sequence_test_params{ "I32", { 3, 3, 3 },{ 2, 2, 2 },  0, 0, test0 },
254                 reverse_sequence_test_params{ "I32", { 3, 3, 3 },{ 2, 2, 2 }, -3, 0, test0 },
255                 reverse_sequence_test_params{ "I32", { 3, 3, 3 },{ 2, 2, 2 },  1, 0, test2 },
256                 reverse_sequence_test_params{ "I32", { 3, 3, 3 },{ 2, 2, 2 }, -2, 0, test2 },
257                 reverse_sequence_test_params{ "I32", { 3, 3, 3 },{ 2, 2, 2 },  2, 1, test4 },
258 /*  5 */        reverse_sequence_test_params{ "I32", { 3, 3, 3 },{ 2, 2, 2 }, -1, 1, test4 },
259                 reverse_sequence_test_params{ "I32", { 2, 3 },{ 3, 2 }, 1, 0, test6 },
260                 reverse_sequence_test_params{ "I32", { 3, 3, 3 },{ 1, 2, 3 },  1, 0, test7 },
261                 reverse_sequence_test_params{ "I32", { 3, 3, 3 },{ 1, 2, 3 },  1,-3, test7 },
262                 reverse_sequence_test_params{ "I32", { 3, 3, 3 },{ 1, 2, 3 },  1, 2, test8 },
263                 reverse_sequence_test_params{"FP32", { 3, 3, 3 },{ 2, 2, 2 },  0, 0, test0 },
264                 reverse_sequence_test_params{"FP32", { 3, 3, 3 },{ 2, 2, 2 }, -3, 0, test0 },
265                 reverse_sequence_test_params{"FP32", { 3, 3, 3 },{ 2, 2, 2 },  1, 0, test2 },
266                 reverse_sequence_test_params{"FP32", { 3, 3, 3 },{ 2, 2, 2 }, -2, 0, test2 },
267                 reverse_sequence_test_params{"FP32", { 3, 3, 3 },{ 2, 2, 2 },  2, 1, test4 },
268                 reverse_sequence_test_params{"FP32", { 3, 3, 3 },{ 2, 2, 2 }, -1, 1, test4 },
269 /* 15 */        reverse_sequence_test_params{"FP32", { 2, 3 },{ 3, 2 }, 1, 0, test6 },
270                 reverse_sequence_test_params{"FP32", { 3, 3, 3 },{ 1, 2, 3 },  1, 0, test7 },
271                 reverse_sequence_test_params{"FP32", { 3, 3, 3 },{ 1, 2, 3 },  1,-3, test7 },
272                 reverse_sequence_test_params{"FP32", { 3, 3, 3 },{ 1, 2, 3 },  1, 2, test8 }
273             ));