1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
5 #include <mock_icnn_network.hpp>
6 #include "gna_matcher.hpp"
7 #include <gna/gna_config.hpp>
8 #include <gna-api-types-xnn.h>
9 #include <gna_plugin/gna_executable_network.hpp>
10 #include "gna_plugin.hpp"
11 #include "gna_mock_api.hpp"
12 #include "matchers/precision_matcher.hpp"
13 #include "matchers/pwl_matcher.hpp"
14 #include "matchers/copy_matcher.hpp"
15 #include "matchers/diag_matcher.hpp"
16 #include "matchers/pwl_quantization_metrics_matcher.hpp"
17 #include "matchers/conv_matcher.hpp"
18 #include "matchers/pool_matcher.hpp"
19 #include "matchers/fill_with_data.hpp"
20 #include "matchers/weights_matcher.hpp"
22 #include <gmock/gmock-generated-actions.h>
23 #include <gmock/gmock-more-actions.h>
24 #include "gmock/gmock.h"
25 #include "matchers/input_data_matcher.hpp"
26 #include <inference_engine/blob_factory.hpp>
27 #include <details/ie_cnn_network_tools.h>
30 using namespace InferenceEngine;
31 using namespace GNAPluginNS;
32 using namespace ::testing;
34 class NullAllocator : public IAllocator {
41 delete[] static_cast<char*>(ptr);
43 void * lock(void * handle, LockOp = LOCK_FOR_WRITE) noexcept override {
46 void unlock(void * handle) noexcept override {
49 void * alloc(size_t size) noexcept override {
52 virtual bool free(void* handle) noexcept {
55 virtual void Release() noexcept {
60 std::vector<CNNLayerPtr> TIBodySortTopologically(const TensorIterator::Body &body) {
61 std::vector<CNNLayerPtr> all_layers;
63 auto getAllInputs = [&](const std::vector<DataPtr> &heads) {
64 CNNLayerSet inputLayers;
65 std::unordered_set<CNNLayer *> allLayers;
67 // Define all start layers
68 for (const auto &data : heads) {
69 auto &secondLayers = data->getInputTo();
71 details::UnorderedDFS(allLayers, secondLayers.begin()->second, [&](CNNLayerPtr layer) {
72 if (layer->insData.empty()) {
73 inputLayers.insert(layer);
78 std::vector<DataPtr> res = heads;
79 // Add fake input data to point on not achievable
80 // layers from head (like const placeholders)
81 for (auto &starter : inputLayers) {
82 DataPtr holder(new Data(starter->name + ":input_holder", starter->precision));
83 holder->getInputTo()[starter->name] = starter;
84 res.push_back(holder);
89 auto all_input_layers = getAllInputs(body.inputs);
90 CNNNetForestDFS(all_input_layers, [&](CNNLayerPtr current){
91 all_layers.push_back(current);
93 std::reverse(all_layers.begin(), all_layers.end());
97 void GNAPropagateMatcher :: match() {
99 // matching gna propagate forward call.
100 GNAPlugin plugin(_env.config);
101 plugin.SetPolicy(_env.policy);
102 size_t inputSize = 10;
103 size_t outputSize = 10;
104 InputsDataMap inputsInfo;
105 OutputsDataMap outputsInfo;
107 auto loadNetworkFromIR = [&] () {
108 CNNNetReader net_reader;
109 ASSERT_NO_THROW_IE_EXCEPTION(net_reader.ReadNetwork(_env.model.data(), _env.model.length()));
111 auto weights_fake = make_shared<TBlob<uint8_t>>(Precision::U8, C, SizeVector({std::numeric_limits<uint32_t>::max()}), make_shared<NullAllocator>());
112 net_reader.SetWeights(weights_fake);
114 auto net_original = net_reader.getNetwork();
115 auto input_dims = net_original.getInputsInfo().begin()->second->getTensorDesc().getDims();
116 auto output = net_original.getOutputsInfo();
117 // sometimes network might be created without outputs - ex memory output only
118 auto output_dims = !output.empty() ? output.begin()->second->getTensorDesc().getDims() : input_dims;
120 inputSize = details::product(std::begin(input_dims), std::end(input_dims));
121 outputSize = details::product(std::begin(output_dims), std::end(output_dims));
123 size_t weightsSize = 0;
124 std::vector<std::string> dataBlobs = {
130 std::vector<InferenceEngine::CNNLayerPtr> tiBodies;
131 for (auto &layer : net_original) {
132 if (layer->type == "TensorIterator") {
133 auto tiBody = TIBodySortTopologically(std::dynamic_pointer_cast<InferenceEngine::TensorIterator>(layer)->body);
134 tiBodies.insert(tiBodies.end(), tiBody.begin(), tiBody.end());
137 std::vector<CNNLayerPtr> sortedLayers = details::CNNNetSortTopologically(net_original);
138 sortedLayers.insert(sortedLayers.end(), tiBodies.begin(), tiBodies.end());
140 for (auto &layer : sortedLayers) {
141 for (auto &blobName : dataBlobs) {
142 auto weights = layer->blobs[blobName];
144 weightsSize += weights->byteSize();
149 auto weights = make_shared_blob<uint8_t >({ Precision::U8, {weightsSize}, Layout::C });
152 if (!_env.weightsFillPattern.empty()) {
153 GNATest::fillWeights(weights, _env.weightsFillPattern);
155 GNATest::fillWeights(weights);
157 net_reader.SetWeights(weights);
159 net_reader.getNetwork().setTargetDevice(_env.target_device);
162 auto network = net_reader.getNetwork();
166 plugin.LoadNetwork(net_reader.getNetwork());
168 inputsInfo = net_reader.getNetwork().getInputsInfo();
169 outputsInfo = net_reader.getNetwork().getOutputsInfo();
172 auto loadNetworkFromAOT = [&] () {
173 auto sp = plugin.ImportNetwork(_env.importedModelFileName);
174 inputsInfo = plugin.GetInputs();
175 outputsInfo = plugin.GetOutputs();
178 std::map<std::string, Blob::Ptr> input;
179 TBlob<float>::Ptr output;
185 auto loadNetwork = [&]() {
186 if (!_env.importedModelFileName.empty()) {
187 ASSERT_NO_FATAL_FAILURE(loadNetworkFromAOT());
189 ASSERT_NO_FATAL_FAILURE(loadNetworkFromIR());
191 const int channel_idx = 1;
192 bool haveInputs = !_env.input_init.empty();
193 for (auto && info :inputsInfo) {
194 decltype(_env.input_init)::iterator it;
195 auto & inputBlob = input[info.first];
197 if (inputsInfo.size() != 1) {
198 ASSERT_NE(it = _env.input_init.find(info.first), _env.input_init.end());
200 ASSERT_NE(0, _env.input_init.size());
201 it = _env.input_init.begin();
203 in_C = it->second.size();
204 ASSERT_EQ(in_C, info.second->getTensorDesc().getDims()[channel_idx]);
207 inputBlob = make_blob_with_precision({ _env.input_precision, info.second->getTensorDesc().getDims(),
208 info.second->getLayout() });
209 inputBlob->allocate();
211 if (_env.input_precision == Precision::FP32) {
212 std::copy_n(it->second.cbegin(), in_N * in_C, inputBlob->buffer().as<float *>());
213 } else if (_env.input_precision == Precision::U8) {
214 std::copy_n(it->second.cbegin(), in_N * in_C, inputBlob->buffer().as<uint8_t *>());
216 std::logic_error(std::string("Unsupported input precision: ") + _env.input_precision.name());
221 out_C = _env.matchOutput == true ? _env.expected_output.size() : outputSize;
222 output.reset(new TBlob<float>({ Precision::FP32, {out_N, out_C}, Layout::NC }));
227 StrictMock<GNACppApi> mockApi;
228 std::vector<uint8_t> data;
230 if (_env.target_device == InferenceEngine::TargetDevice::eGNA &&
233 EXPECT_CALL(mockApi, GNAAlloc(_,_,_)).WillOnce(Invoke([&data](
234 intel_gna_handle_t nGNADevice, // handle to GNA accelerator
235 uint32_t sizeRequested,
236 uint32_t* sizeGranted
238 data.resize(sizeRequested);
239 *sizeGranted = sizeRequested;
240 return &data.front();
242 EXPECT_CALL(mockApi, GNADeviceOpenSetThreads(_, _)).WillOnce(Return(1));
244 if(_env.is_profiling_enabled == false) {
245 EXPECT_CALL(mockApi, GNAWait(_, _, _)).WillOnce(Return(GNA_NOERROR));
247 EXPECT_CALL(mockApi, GNAWaitPerfRes(_, _, _, _)).WillOnce(Return(GNA_NOERROR));
250 if(_env.is_setup_of_omp_theads_expected == true) {
251 EXPECT_CALL(mockApi, gmmSetThreads(_)).Times(1);
253 EXPECT_CALL(mockApi, gmmSetThreads(_)).Times(0);
256 std::unique_ptr<NNetComponentMatcher> combined(new NNetComponentMatcher());
258 for (auto & matchWhat : _env.whatToMatch) {
260 case GnaPluginTestEnvironment::matchPrecision :
261 combined->add(new NNetPrecisionMatcher(_env.nnet_precision, INTEL_AFFINE));
263 case GnaPluginTestEnvironment::matchProcType :
264 EXPECT_CALL(mockApi, GNAPropagateForward(_, _, _, _, _, Eq(_env.proc_type)))
265 .WillOnce(Return(GNA_NOERROR));
267 case GnaPluginTestEnvironment::matchPwlInserted :
268 combined->add(new PWLMatcher(_env.matchInserted, _env.matchQuantity, _env.pwlsToMatchWith));
270 case GnaPluginTestEnvironment::matchConvInserted:
271 combined->add(new ConvoluionLayerMatcher(_env.matchInserted, _env.matchQuantity));
273 case GnaPluginTestEnvironment::matchMaxPoolingInserted:
274 combined->add(new PoolingLayerMatcher(_env.matchInserted, _env.matchQuantity, true));
276 case GnaPluginTestEnvironment::matchPwlQuantizeMetrics :
277 combined->add(new PWLQuantizationMetricsMatcher(_env.type,
278 _env.quantization_presicion_threshold,
279 _env.quantization_segments_threshold));
281 case GnaPluginTestEnvironment::matchCopyInserted :
282 combined->add(new CopyLayerMatcher(_env.matchInserted, _env.matchQuantity));
284 case GnaPluginTestEnvironment::matchDiagonalInserted :
285 combined->add(new DiagLayerMatcher(_env.matchInserted, _env.matchQuantity));
287 case GnaPluginTestEnvironment::saveArgs :
288 EXPECT_CALL(mockApi, GNAPropagateForward(_, _, _, _, _, _))
289 .WillOnce(DoAll(SaveArgPointee<1>(savedNet), Return(GNA_NOERROR)));
291 case GnaPluginTestEnvironment::matchInputData :
292 combined->add(new InputDataMatcher(_env.input_processed));
294 case GnaPluginTestEnvironment::fillOutputValues :
295 combined->add(new OutputFiller(_env.fillValue, _env.fillValue));
297 case GnaPluginTestEnvironment::matchAffineWeightsTranspose:
298 HasWeightsTranspozed(combined, _env.transposedData, _env.transposeArgs);
300 case GnaPluginTestEnvironment::matchAffineWeights:
301 HasWeightsEq(combined, _env.transposedData);
303 case GnaPluginTestEnvironment::saveAffineWeights:
304 SaveWeights(combined, _env.transposedData, _env.transposedArgsForSaving);
307 EXPECT_CALL(mockApi, GNAPropagateForward(_, _, _, _, _, _))
308 .WillOnce(Return(GNA_NOERROR));
312 if (combined && !combined->empty()) {
313 EXPECT_CALL(mockApi, GNAPropagateForward(_, ::testing::MakeMatcher(combined.release()), _, _, _,_)).WillOnce(Return(GNA_NOERROR));
319 if (!inputsInfo.empty()) {
320 BlobMap input_blob_map;
321 BlobMap output_blob_map;
322 for (auto info : inputsInfo) {
323 size_t current_size = InferenceEngine::details::product(info.second->getTensorDesc().getDims());
324 input_blob_map[info.first] = input[info.first];
327 for (auto info : outputsInfo) {
328 size_t current_size = InferenceEngine::details::product(info.second->getTensorDesc().getDims());
329 output_blob_map[info.first] = make_shared_blob<float>(
330 { info.second->getPrecision(),
331 {1, details::product(info.second->getTensorDesc().getDims())}, NC },
332 output->data() + offset, current_size * sizeof(float));
333 offset += current_size;
336 plugin.Infer(input_blob_map, output_blob_map);
339 plugin.Infer(*input.begin()->second, *output);
343 if (_env.matchOutput) {
344 std::vector<float> actual_output(output->size());
346 std::copy_n(output->cbuffer().as<float *>(), out_C * out_N, actual_output.begin());
348 for (auto ref = _env.expected_output.begin(); ref != _env.expected_output.end(); ref++ ) {
349 auto idx = std::distance( _env.expected_output.begin(), ref);
350 ASSERT_FLOAT_EQ(*ref, actual_output[idx]) << "at "<< idx;
354 std::map<std::string, InferenceEngine::InferenceEngineProfileInfo> perfMap;
355 plugin.GetPerformanceCounts(perfMap);
357 if(_env.is_profiling_enabled != false) {
358 ASSERT_NE(perfMap.empty(),true);
360 ASSERT_NE(perfMap.empty(),false);
364 catch(std::exception &ex) {
365 if (!_env.matchThrows) {
370 if (!_env.matchThrows) {
371 FAIL() << "unknown exception thrown";
377 void GNAPluginCreationMatcher :: match() {
378 if (_env.matchThrows) {
379 ASSERT_ANY_THROW(GNAPlugin(_env.config));
382 GNAPlugin(_env.config);
386 void GNAPluginAOTMatcher :: match() {
387 // matching gna_propagate forward call.
389 CNNNetReader net_reader;
390 ASSERT_NO_THROW_IE_EXCEPTION(net_reader.ReadNetwork(_env.model.data(), _env.model.length()));
392 size_t weightsSize = 440*3;
394 auto weights = make_shared_blob<uint8_t >({ Precision::U8, {weightsSize}, Layout::C });
396 GNATest::fillWeights(weights);
397 net_reader.SetWeights(weights);
399 GNAPlugin plugin(_env.config);
401 TBlob<float> input({ Precision::FP32, {1, 10}, Layout::NC });
405 TBlob<float> output({ Precision::FP32, {1, 10}, Layout::NC });
408 net_reader.getNetwork().setTargetDevice(TargetDevice::eGNA);
411 auto network = net_reader.getNetwork();
416 std::vector<uint8_t> data(10000);
417 EXPECT_CALL(mockApi, GNAAlloc(_,_,_)).WillOnce(DoAll(SetArgPointee<2>(10000), Return(&data.front())));
418 EXPECT_CALL(mockApi, GNADeviceOpenSetThreads(_, _)).WillOnce(Return(1));
420 plugin.LoadNetwork(net_reader.getNetwork());
421 plugin.Export(_env.exportedModelFileName);
425 void GNADumpXNNMatcher::load(GNAPlugin & plugin) {
427 // matching gna DumpXNN forward call.
428 plugin = GNAPlugin(_env.config);
430 auto loadNetworkFromIR = [&]() {
432 CNNNetReader net_reader;
433 ASSERT_NO_THROW_IE_EXCEPTION(net_reader.ReadNetwork(_env.model.data(), _env.model.length()));
435 size_t weightsSize = 440 * 3;
437 auto weights = make_shared_blob<uint8_t>({ Precision::U8, {weightsSize}, Layout::C });
439 GNATest::fillWeights(weights);
440 net_reader.SetWeights(weights);
442 net_reader.getNetwork().setTargetDevice(TargetDevice::eGNA);
445 auto network = net_reader.getNetwork();
449 plugin.LoadNetwork(net_reader.getNetwork());
452 auto loadNetworkFromAOT = [&]() {
453 plugin.ImportNetwork(_env.importedModelFileName);
456 auto loadNetwork = [&]() {
457 if (!_env.importedModelFileName.empty()) {
458 loadNetworkFromAOT();
467 void GNADumpXNNMatcher::match() {
470 std::vector<uint8_t> data(10000);
471 if (!_env.matchThrows) {
473 EXPECT_CALL(mockApi, GNAAlloc(_,_,_)).WillOnce(DoAll(SetArgPointee<2>(10000), Return(&data.front())));
474 EXPECT_CALL(mockApi, GNADeviceOpenSetThreads(_, _)).WillOnce(Return(1));
475 intel_gna_model_header header = {};
476 header.model_size = 1;
477 EXPECT_CALL(mockApi, GNADumpXnn(_, _, _, _, _,_)).WillOnce(DoAll(SetArgPointee<3>(header), Return((void*)::operator new(1))));
478 EXPECT_CALL(mockApi, GNAFree(_)).WillOnce(Return(GNA_NOERROR));
479 EXPECT_CALL(mockApi, GNADeviceClose(_)).WillOnce(Return(GNA_NOERROR));
483 // matching gna DumpXNN forward call.
484 GNAPluginNS::GNAPlugin plugin;
487 catch(std::exception &ex) {
488 if (!_env.matchThrows) {
493 if (!_env.matchThrows) {
494 FAIL() << "unknown exception thrown";
500 void GNAQueryStateMatcher :: match() {
502 // TODO : avoid copy pastes
504 std::vector<uint8_t> data(10000);
506 std::shared_ptr<IExecutableNetworkInternal> executer;
507 auto loadNetworkFromIR = [&]() {
509 CNNNetReader net_reader;
510 ASSERT_NO_THROW_IE_EXCEPTION(net_reader.ReadNetwork(_env.model.data(), _env.model.length()));
512 size_t weightsSize = 440 * 3;
514 auto weights = make_shared_blob<uint8_t>({ Precision::U8, {weightsSize}, Layout::C });
516 GNATest::fillWeights(weights);
517 net_reader.SetWeights(weights);
519 net_reader.getNetwork().setTargetDevice(TargetDevice::eGNA);
522 auto network = net_reader.getNetwork();
526 executer.reset(new GNAExecutableNetwork(net_reader.getNetwork(), _env.config));
529 auto loadNetworkFromAOT = [&]() {
530 executer.reset(new GNAExecutableNetwork(_env.importedModelFileName, _env.config));
533 auto loadNetwork = [&]() {
534 if (!_env.importedModelFileName.empty()) {
535 return loadNetworkFromAOT();
537 return loadNetworkFromIR();
542 EXPECT_CALL(mockApi, GNAAlloc(_,_,_)).WillOnce(DoAll(SetArgPointee<2>(10000), Return(&data.front())));
543 EXPECT_CALL(mockApi, GNADeviceOpenSetThreads(_, _)).WillOnce(Return(1));
544 EXPECT_CALL(mockApi, GNAFree(_)).WillOnce(Return(GNA_NOERROR));
545 EXPECT_CALL(mockApi, GNADeviceClose(_)).WillOnce(Return(GNA_NOERROR));
549 if (GnaPluginTestEnvironment::kAnyNotNull == _env.numberOfStates) {
550 auto states = executer->QueryState();
551 ASSERT_NE(states.size(), 0);
552 // usually states are callable
553 for (auto & state : states) {
556 } else if (_env.numberOfStates >= 0) {
557 ASSERT_EQ(executer->QueryState().size(), _env.numberOfStates);
559 FAIL() << "number of memory states expectation not set";
563 catch(std::exception &ex) {
567 FAIL() << "unknown exception thrown";