Use metadata from executable network when fetching results of the infer request;...
[platform/upstream/dldt.git] / inference-engine / tests / ie_test_utils / functional_test_utils / layer_test_utils.cpp
1 // Copyright (C) 2019-2020 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4
5 #include <transformations/convert_batch_to_space.hpp>
6 #include <transformations/convert_space_to_batch.hpp>
7
8 #include "layer_test_utils.hpp"
9
10 namespace LayerTestsUtils {
11
12 LayerTestsCommon::LayerTestsCommon() : threshold(1e-2f) {
13     core = PluginCache::get().ie(targetDevice);
14 }
15
16 void LayerTestsCommon::Run() {
17     SKIP_IF_CURRENT_TEST_IS_DISABLED()
18
19     ConfigurePlugin();
20     LoadNetwork();
21     Infer();
22     Validate();
23 }
24
25 LayerTestsCommon::~LayerTestsCommon() {
26     if (!configuration.empty()) {
27         PluginCache::get().reset();
28     }
29 }
30
31 InferenceEngine::Blob::Ptr LayerTestsCommon::GenerateInput(const InferenceEngine::InputInfo &info) const {
32     return FuncTestUtils::createAndFillBlob(info.getTensorDesc());
33 }
34
35 void LayerTestsCommon::Compare(const std::vector<std::uint8_t> &expected, const InferenceEngine::Blob::Ptr &actual) {
36     ASSERT_EQ(expected.size(), actual->byteSize());
37     const auto &expectedBuffer = expected.data();
38
39     auto memory = InferenceEngine::as<InferenceEngine::MemoryBlob>(actual);
40     IE_ASSERT(memory);
41     const auto lockedMemory = memory->wmap();
42     const auto actualBuffer = lockedMemory.as<const std::uint8_t *>();
43
44     const auto &precision = actual->getTensorDesc().getPrecision();
45     auto bufferSize = actual->size();
46     // With dynamic batch, you need to size
47     if (configuration.count(InferenceEngine::PluginConfigParams::KEY_DYN_BATCH_ENABLED)) {
48         auto batchSize = actual->getTensorDesc().getDims()[0];
49         auto halfBatchSize = batchSize > 1 ? batchSize/ 2 : 1;
50         bufferSize = (actual->size() * halfBatchSize / batchSize);
51     }
52     const auto &size = bufferSize;
53     switch (precision) {
54         case InferenceEngine::Precision::FP32:
55             Compare(reinterpret_cast<const float *>(expectedBuffer), reinterpret_cast<const float *>(actualBuffer),
56                     size, threshold);
57             break;
58         case InferenceEngine::Precision::I32:
59             Compare(reinterpret_cast<const std::int32_t *>(expectedBuffer),
60                     reinterpret_cast<const std::int32_t *>(actualBuffer), size, 0);
61             break;
62         default:
63             FAIL() << "Comparator for " << precision << " precision isn't supported";
64     }
65 }
66
67 void LayerTestsCommon::Compare(const InferenceEngine::Blob::Ptr &expected, const InferenceEngine::Blob::Ptr &actual) {
68     auto get_raw_buffer = [] (const InferenceEngine::Blob::Ptr &blob) {
69         auto memory = InferenceEngine::as<InferenceEngine::MemoryBlob>(blob);
70         IE_ASSERT(memory);
71         const auto lockedMemory = memory->wmap();
72         return lockedMemory.as<const std::uint8_t *>();
73     };
74     const auto expectedBuffer = get_raw_buffer(expected);
75     const auto actualBuffer = get_raw_buffer(actual);
76
77     const auto &precision = actual->getTensorDesc().getPrecision();
78     const auto &size = actual->size();
79     switch (precision) {
80         case InferenceEngine::Precision::FP32:
81             Compare(reinterpret_cast<const float *>(expectedBuffer), reinterpret_cast<const float *>(actualBuffer),
82                     size, threshold);
83             break;
84         case InferenceEngine::Precision::I32:
85             Compare(reinterpret_cast<const std::int32_t *>(expectedBuffer),
86                     reinterpret_cast<const std::int32_t *>(actualBuffer), size, 0);
87             break;
88         default:
89             FAIL() << "Comparator for " << precision << " precision isn't supported";
90     }
91 }
92
93 void LayerTestsCommon::ConfigurePlugin() {
94     if (!configuration.empty()) {
95         core->SetConfig(configuration, targetDevice);
96     }
97 }
98
99 void LayerTestsCommon::ConfigureNetwork() const {
100     for (const auto &in : cnnNetwork.getInputsInfo()) {
101         if (inLayout != InferenceEngine::Layout::ANY) {
102             in.second->setLayout(inLayout);
103         }
104         if (inPrc != InferenceEngine::Precision::UNSPECIFIED) {
105             in.second->setPrecision(inPrc);
106         }
107     }
108
109     for (const auto &out : cnnNetwork.getOutputsInfo()) {
110         if (outLayout != InferenceEngine::Layout::ANY) {
111             out.second->setLayout(outLayout);
112         }
113         if (outPrc != InferenceEngine::Precision::UNSPECIFIED) {
114             out.second->setPrecision(outPrc);
115         }
116     }
117 }
118
119 void LayerTestsCommon::LoadNetwork() {
120     cnnNetwork = InferenceEngine::CNNNetwork{function};
121     ConfigureNetwork();
122     executableNetwork = core->LoadNetwork(cnnNetwork, targetDevice);
123 }
124
125 void LayerTestsCommon::Infer() {
126     inferRequest = executableNetwork.CreateInferRequest();
127     inputs.clear();
128
129     for (const auto &input : executableNetwork.GetInputsInfo()) {
130         const auto &info = input.second;
131         auto blob = GenerateInput(*info);
132         inferRequest.SetBlob(info->name(), blob);
133         inputs.push_back(blob);
134     }
135     if (configuration.count(InferenceEngine::PluginConfigParams::KEY_DYN_BATCH_ENABLED) &&
136         configuration.count(InferenceEngine::PluginConfigParams::YES)) {
137         auto batchSize = executableNetwork.GetInputsInfo().begin()->second->getTensorDesc().getDims()[0] / 2;
138         inferRequest.SetBatch(batchSize);
139     }
140     inferRequest.Infer();
141 }
142
143 std::vector<std::vector<std::uint8_t>> LayerTestsCommon::CalculateRefs() {
144     // nGraph interpreter does not support f16
145     // IE converts f16 to f32
146     ngraph::pass::ConvertPrecision<ngraph::element::Type_t::f16, ngraph::element::Type_t::f32>().run_on_function(function);
147     function->validate_nodes_and_infer_types();
148     auto referenceInputs = std::vector<std::vector<std::uint8_t>>(inputs.size());
149     for (std::size_t i = 0; i < inputs.size(); ++i) {
150         const auto& input = inputs[i];
151         const auto& inputSize = input->byteSize();
152
153         auto& referenceInput = referenceInputs[i];
154         referenceInput.resize(inputSize);
155
156         auto memory = InferenceEngine::as<InferenceEngine::MemoryBlob>(input);
157         IE_ASSERT(memory);
158         const auto lockedMemory = memory->wmap();
159         const auto buffer = lockedMemory.as<const std::uint8_t*>();
160         std::copy(buffer, buffer + inputSize, referenceInput.data());
161     }
162
163     auto ieOutPrc = outPrc;
164     if (outPrc == InferenceEngine::Precision::UNSPECIFIED) {
165         const auto &actualOutputs = GetOutputs();
166         ieOutPrc = actualOutputs[0]->getTensorDesc().getPrecision();
167     }
168
169     const auto &convertType = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(ieOutPrc);
170     std::vector<std::vector<std::uint8_t>> expectedOutputs;
171     switch (refMode) {
172         case INTERPRETER: {
173             expectedOutputs = ngraph::helpers::interpreterFunction(function, referenceInputs, convertType);
174             break;
175         }
176         case CONSTANT_FOLDING: {
177             const auto &foldedFunc = ngraph::helpers::foldFunction(function, referenceInputs);
178             expectedOutputs = ngraph::helpers::getConstData(foldedFunc, convertType);
179             break;
180         }
181         case IE: {
182             // reference inference on device with other options and nGraph function has to be implemented here
183             break;
184         }
185         case INTERPRETER_TRANSFORMATIONS: {
186             auto cloned_function = ngraph::clone_function(*function);
187
188             // todo: add functionality to configure the necessary transformations for each test separately
189             ngraph::pass::Manager m;
190             m.register_pass<ngraph::pass::ConvertSpaceToBatch>();
191             m.register_pass<ngraph::pass::ConvertBatchToSpace>();
192             m.run_passes(cloned_function);
193             expectedOutputs = ngraph::helpers::interpreterFunction(cloned_function, referenceInputs, convertType);
194             break;
195         }
196     }
197
198     return expectedOutputs;
199 }
200
201 std::vector<InferenceEngine::Blob::Ptr> LayerTestsCommon::GetOutputs() {
202     auto outputs = std::vector<InferenceEngine::Blob::Ptr>{};
203     for (const auto &output : executableNetwork.GetOutputsInfo()) {
204         const auto &name = output.first;
205         outputs.push_back(inferRequest.GetBlob(name));
206     }
207     return outputs;
208 }
209
210 void LayerTestsCommon::Compare(const std::vector<std::vector<std::uint8_t>>& expectedOutputs, const std::vector<InferenceEngine::Blob::Ptr>& actualOutputs) {
211     for (std::size_t outputIndex = 0; outputIndex < expectedOutputs.size(); ++outputIndex) {
212         const auto& expected = expectedOutputs[outputIndex];
213         const auto& actual = actualOutputs[outputIndex];
214         Compare(expected, actual);
215     }
216 }
217
218 void LayerTestsCommon::Validate() {
219     auto expectedOutputs = CalculateRefs();
220     const auto& actualOutputs = GetOutputs();
221
222     if (expectedOutputs.empty()) {
223         return;
224     }
225
226     IE_ASSERT(actualOutputs.size() == expectedOutputs.size())
227         << "nGraph interpreter has " << expectedOutputs.size() << " outputs, while IE " << actualOutputs.size();
228
229     Compare(expectedOutputs, actualOutputs);
230 }
231
232 void LayerTestsCommon::SetRefMode(RefMode mode) {
233     refMode = mode;
234 }
235 }  // namespace LayerTestsUtils