Publishing R4 (#41)
[platform/upstream/dldt.git] / inference-engine / src / cldnn_engine / cldnn_infer_request.cpp
1 // Copyright (C) 2018 Intel Corporation
2 //
3 // SPDX-License-Identifier: Apache-2.0
4 //
5
6 #include <algorithm>
7 #include <string>
8 #include <map>
9 #include <functional>
10 #include <CPP/detection_output.hpp>  // todo: find a way to remove this
11 #include <description_buffer.hpp>
12 #include "cldnn_infer_request.h"
13
14 using namespace InferenceEngine;
15
16 namespace CLDNNPlugin {
17
18 const std::string CLDNNInferRequest::fp32_suffix = "_fp32";
19
20 Blob::Ptr CLDNNInferRequest::createInputBlob(const TensorDesc& desc, uint8_t* mem_ptr) {
21     const Layout l = desc.getLayout();
22     const Precision p = desc.getPrecision();
23     const SizeVector sz = SizeVector(desc.getDims().rbegin(), desc.getDims().rend());
24
25     switch (p) {
26     case Precision::FP32:
27         if (mem_ptr != nullptr)
28             return make_shared_blob<float>(p, l, sz, reinterpret_cast<float*>(mem_ptr));
29         else
30             return make_shared_blob<float, const SizeVector>(p, l, sz);
31     case Precision::FP16:
32         if (mem_ptr != nullptr)
33             return make_shared_blob<uint16_t>(p, l, sz, reinterpret_cast<uint16_t*>(mem_ptr));
34         else
35             return make_shared_blob<uint16_t, const SizeVector>(p, l, sz);
36     case Precision::I16:
37         if (mem_ptr != nullptr)
38             return make_shared_blob<int16_t>(p, l, sz, reinterpret_cast<int16_t*>(mem_ptr));
39         else
40             return make_shared_blob<int16_t, const SizeVector>(p, l, sz);
41     case Precision::U8:
42         if (mem_ptr != nullptr)
43             return make_shared_blob<uint8_t>(p, l, sz, reinterpret_cast<uint8_t*>(mem_ptr));
44         else
45             return make_shared_blob<uint8_t, const SizeVector>(Precision::U8, l, sz);
46     default:
47         THROW_IE_EXCEPTION << "The plugin does not support input " << p.name() << " precision";
48     }
49 }
50
51 Blob::Ptr CLDNNInferRequest::createOutputBlob(const TensorDesc& desc, uint8_t* mem_ptr) {
52     const Layout l = desc.getLayout();
53     const Precision p = desc.getPrecision();
54     const SizeVector sz = SizeVector(desc.getDims().rbegin(), desc.getDims().rend());
55
56     switch (p) {
57     case Precision::FP32:
58         if (mem_ptr != nullptr)
59             return make_shared_blob<float>(p, l, sz, reinterpret_cast<float*>(mem_ptr));
60         else
61             return make_shared_blob<float, const SizeVector>(p, l, sz);
62     case Precision::FP16:
63         if (mem_ptr != nullptr)
64             return make_shared_blob<uint16_t>(p, l, sz, reinterpret_cast<uint16_t*>(mem_ptr));
65         else
66             return make_shared_blob<uint16_t, const SizeVector>(p, l, sz);
67     default:
68         THROW_IE_EXCEPTION << "The plugin does not support output " << p.name() << " precision";
69     }
70 }
71
72 void CLDNNInferRequest::copyOutputData(const cldnn::memory& outputMemory,
73                                         Blob::Ptr bptr,
74                                         buf_info* bi) {
75     size_t n = (bi == nullptr) ? bptr->size() : bi->buf_size;
76     size_t offset = (bi == nullptr) ? 0 : bi->buf_offset;
77
78     auto layout = outputMemory.get_layout();
79     auto size = layout.size;
80     auto l_padd = layout.data_padding.lower_size();
81     auto u_padd = layout.data_padding.upper_size();
82
83     auto h_padding = u_padd.spatial[0] + l_padd.spatial[0];
84     auto v_padding_l = (h_padding + size.spatial[0]) * u_padd.spatial[1];
85     auto v_padding_u = (h_padding + size.spatial[0]) * l_padd.spatial[1];
86
87     switch (bptr->precision()) {
88     case Precision::FP32: {
89         TBlob<float>::Ptr out_f = std::dynamic_pointer_cast<TBlob<float>>(bptr);
90         if (out_f == nullptr) {
91             THROW_IE_EXCEPTION << "Invalid output blob";
92         }
93         auto resPtr = outputMemory.pointer<float>();
94         float *resVec = out_f->data() + offset;
95
96         if (h_padding || v_padding_l || v_padding_u) {
97             size_t i = 0;
98             for (size_t b = 0; b < size.batch[0]; b++) {
99                 for (size_t f = 0; f < size.feature[0]; f++) {
100                     i += v_padding_l;
101                     for (size_t y = 0; y < size.spatial[1]; y++) {
102                         i += l_padd.spatial[0];
103                         for (size_t x = 0; x < size.spatial[0]; x++, i++) {
104                             *resVec++ = resPtr[i];
105                         }
106                         i += u_padd.spatial[0];
107                     }
108                     i += v_padding_u;
109                 }
110             }
111         } else {
112             for (size_t i = 0; i < n; i++) {
113                 resVec[i] = resPtr[i];
114             }
115         }
116     }
117     break;
118     case Precision::FP16: {
119         TBlob<uint16_t>::Ptr out_f = std::dynamic_pointer_cast<TBlob<uint16_t>>(bptr);
120         if (out_f == nullptr) {
121             THROW_IE_EXCEPTION << "Invalid output blob";
122         }
123         auto resPtr = outputMemory.pointer<uint16_t>();
124         uint16_t *resVec = out_f->data() + offset;
125
126         if (h_padding || v_padding_l || v_padding_u) {
127             size_t i = 0;
128             for (size_t b = 0; b < size.batch[0]; b++) {
129                 for (size_t f = 0; f < size.feature[0]; f++) {
130                     i += v_padding_l;
131                     for (size_t y = 0; y < size.spatial[1]; y++) {
132                         i += l_padd.spatial[0];
133                         for (size_t x = 0; x < size.spatial[0]; x++, i++) {
134                             *resVec++ = resPtr[i];
135                         }
136                         i += u_padd.spatial[0];
137                     }
138                     i += v_padding_u;
139                 }
140             }
141         } else {
142             for (size_t i = 0; i < n; i++) {
143                 resVec[i] = resPtr[i];
144             }
145         }
146     }
147     break;
148     default:
149         THROW_IE_EXCEPTION << "The plugin does not support output " << bptr->precision() << " precision";
150     }
151 }
152
153 void CLDNNInferRequest::copyInputData(std::shared_ptr<cldnn::network> network,
154                                     const cldnn::primitive_id &inputName,
155                                     const cldnn::layout& inputLayout,
156                                     const Blob &inputBlob, buf_info* bi) {
157     size_t n = (bi == nullptr) ? inputBlob.size() : bi->buf_size;
158     size_t offset = (bi == nullptr) ? 0 : bi->buf_offset;
159
160     switch (inputBlob.precision()) {
161     case Precision::FP32: {
162         float* blob_ptr = const_cast<float*>(inputBlob.cbuffer().as<const float*>()) + offset;
163         network->set_input_data(inputName, cldnn::memory::attach(inputLayout, blob_ptr, n));
164         break;
165     }
166     case Precision::FP16: {
167         uint16_t* blob_ptr = const_cast<uint16_t*>(inputBlob.cbuffer().as<const uint16_t*>()) + offset;
168         network->set_input_data(inputName, cldnn::memory::attach(inputLayout, blob_ptr, n));
169         break;
170     }
171     case Precision::U8: {
172         uint8_t* blob_ptr = const_cast<uint8_t*>(inputBlob.cbuffer().as<const uint8_t*>()) + offset;
173         network->set_input_data(inputName, cldnn::memory::attach(inputLayout, blob_ptr, n));
174         break;
175     }
176     default:
177         THROW_IE_EXCEPTION << "The plugin does not support input " << inputBlob.precision() << " precision";
178     }
179 }
180
181 void CLDNNInferRequest::AllocateInputs() {
182     // allocate inputs
183     for (auto &input : m_env.inputLayouts) {
184         std::string name = input.first;
185         cldnn::layout layout = input.second;
186
187         InputInfo::Ptr ni = _networkInputs.at(input.first);
188         const TensorDesc& desc = ni->getTensorDesc();
189
190         cldnn::memory inputMem = cldnn::memory::allocate(*(m_env.engine), layout);
191         cldnn::pointer<uint8_t> mem_ptr = inputMem.pointer<uint8_t>();
192
193         inputsMemory.insert({ name, inputMem });
194         _inputs[name] = createInputBlob(desc, mem_ptr.data());
195
196         if (desc.getPrecision() == Precision::I16) {
197             cldnn::layout layout_fp32 = layout;
198             layout_fp32.data_type = cldnn::data_types::f32;
199             cldnn::memory inputMem_fp32 = cldnn::memory::allocate(*(m_env.engine), layout_fp32);
200             inputsMemory.insert({ input.first + fp32_suffix, inputMem_fp32 });
201         }
202     }
203 }
204
205 void CLDNNInferRequest::AllocateInputsDyn() {
206     // allocate inputs
207     for (auto &input : m_env.inputLayouts) {
208         InputInfo::Ptr ni = _networkInputs.at(input.first);
209         TensorDesc desc = ni->getTensorDesc();
210         SizeVector& dims = desc.getDims();
211
212         if (!dims.empty()) {
213             *dims.begin() = static_cast<size_t>(m_env.m_max_batch);
214         } else {
215             THROW_IE_EXCEPTION << "Empty dimensions for input blob " << input.first;
216         }
217
218         Blob::Ptr inputBlob = createInputBlob(desc);
219         if (desc.getPrecision() == Precision::I16) {
220             auto fp32inputBlob = InferenceEngine::make_shared_blob<float, const InferenceEngine::SizeVector>(Precision::FP32,
221                                                                                                             desc.getLayout(),
222                                                                                                             desc.getDims());
223             fp32inputBlob->allocate();
224             _inputs[input.first + fp32_suffix] = fp32inputBlob;
225         }
226         inputBlob->allocate();
227         _inputs[input.first] = inputBlob;
228     }
229 }
230
231 void CLDNNInferRequest::AllocateOutputs() {
232     auto networkOutputsIDs = m_env.network->get_output_ids();
233     auto allPrimitiveIds = m_env.network->get_all_primitives();
234
235     // allocate outputs
236     for (auto& no : _networkOutputs) {
237         // Find correct output ID. Start with name stored in IR.
238         std::string outputID = m_env.primitiveIDs.at(no.first);
239         while (std::find(networkOutputsIDs.begin(), networkOutputsIDs.end(), outputID) == networkOutputsIDs.end()) {
240             // If current ID isn't found in cldnn network outputs, get previous primitive id and try again.
241             auto prim = allPrimitiveIds.find(outputID);
242             if (prim == allPrimitiveIds.end()) {
243                 THROW_IE_EXCEPTION << "Unknown primitive id " << outputID;
244             }
245
246             if (m_env.prevPrimitiveIDs.at(outputID).size() != 1 || prim->second != "_optimized_") {
247                 THROW_IE_EXCEPTION << "Unable to find parent for output primitive " << outputID;
248             }
249             outputID = m_env.prevPrimitiveIDs.at(outputID)[0];
250         }
251
252         cldnn::memory output_mem = m_env.network->get_output_memory(outputID);
253         cldnn::pointer<uint8_t> output_mem_ptr = output_mem.pointer<uint8_t>();
254         if (output_mem_ptr.data() == nullptr) {
255             THROW_IE_EXCEPTION << "Empty output memory for primitive " << outputID;
256         }
257
258         DataPtr oi = no.second;
259         const TensorDesc& desc = oi->getTensorDesc();
260
261         _outputs[no.first] = createOutputBlob(desc, output_mem_ptr.data());
262         outputsMap[no.first] = outputID;
263     }
264 }
265
266 void CLDNNInferRequest::AllocateOutputsDyn() {
267     // allocate outputs
268     for (auto& no : _networkOutputs) {
269         DataPtr oi = no.second;
270         TensorDesc desc = oi->getTensorDesc();
271         SizeVector& dims = desc.getDims();
272
273         if (!dims.empty()) {
274             *dims.begin() = static_cast<size_t>(m_env.m_max_batch);
275         } else {
276             THROW_IE_EXCEPTION << "Empty dimensions for output blob " << no.first;
277         }
278
279         Blob::Ptr outputBlob = createOutputBlob(desc);
280         outputBlob->allocate();
281         _outputs[no.first] = outputBlob;
282     }
283 }
284
285 void CLDNNInferRequest::SetBatch(int new_batch) {
286     if (m_env.m_max_batch < 0)
287         THROW_IE_EXCEPTION << "Dynamic batch is not enabled.";
288
289     if (new_batch < 1 || new_batch > m_env.m_max_batch) {
290         THROW_IE_EXCEPTION << "Invalid dynamic batch size " << new_batch <<
291             " for this request.";
292     }
293
294     if (new_batch == m_curBatch)
295         return;
296
297     batchInputs.clear();
298     batchOutputs.clear();
299
300     // tune expected inputs
301     for (auto &input : m_env.inputLayouts) {
302         cldnn::tensor dims = input.second.size;
303         const SizeVector sz = { size_t(dims.spatial[0]), size_t(dims.spatial[1]), size_t(dims.feature[0]), 1 };
304         size_t single_batch = std::accumulate(std::begin(sz), std::end(sz), (size_t)1, std::multiplies<size_t>());
305         std::vector<buf_info> in_buf;
306
307         size_t offset = 0;
308         size_t bsz = single_batch;
309         int b = 0;
310
311         // calculate metadata for input buffers
312         for (unsigned nb = 0; nb < m_env.m_bv_sz; nb++) {
313             unsigned int mask = 1 << nb;
314
315             buf_info ib = { offset, bsz };
316             in_buf.push_back(ib);
317
318             if (new_batch & mask)
319                 offset += bsz;
320             bsz <<= 1;
321         }
322
323         batchInputs[input.first] = in_buf;
324     }
325
326     // tune expected outputs
327     for (auto& no : _networkOutputs) {
328         auto res_output = m_env.outputDims.find(no.first);
329
330         InferenceEngine::SizeVector sz;
331         if (res_output != m_env.outputDims.end())
332             sz = res_output->second;
333         else
334             sz = m_env.outputDims.at(m_env.primitiveIDs.at(no.first));
335
336         sz.back() = 1;
337         size_t single_batch = std::accumulate(std::begin(sz), std::end(sz), (size_t)1, std::multiplies<size_t>());
338         std::vector<buf_info> out_buf;
339
340         size_t offset = 0;
341         size_t bsz = single_batch;
342         int b = 0;
343         // calculate metadata for output buffers
344         for (unsigned nb = 0; nb < m_env.m_bv_sz; nb++) {
345             unsigned int mask = 1 << nb;
346
347             buf_info ob = { offset, bsz };
348             out_buf.push_back(ob);
349
350             if (new_batch & mask)
351                 offset += bsz;
352
353             bsz <<= 1;
354         }
355
356         batchOutputs[no.first] = out_buf;
357     }
358
359     m_curBatch = new_batch;
360 }
361
362 CLDNNInferRequest::CLDNNInferRequest(InferenceEnv env, bool useProfiling,
363                                      InputsDataMap networkInputs, OutputsDataMap networkOutputs)
364         : InferRequestInternal(networkInputs, networkOutputs),
365           m_curBatch(-1),
366           m_env(env),
367           m_useProfiling(useProfiling) {
368     if (m_env.m_max_batch > 1) {
369         AllocateInputsDyn();
370         AllocateOutputsDyn();
371     } else {
372         AllocateInputs();
373         AllocateOutputs();
374     }
375
376     // Fill implementations map
377     if (m_useProfiling) {
378         auto extractImplementationFromInfo = [](const std::string& info) -> std::string {
379             std::string def_implementation = "undef";
380             std::string impl_section = "implementation :";
381             std::string::size_type pos = info.find(impl_section);
382             if (pos == std::string::npos) {
383                 return def_implementation;
384             }
385
386             std::string::size_type end_pos = info.find(',', pos);
387             if (end_pos == std::string::npos) {
388                 return def_implementation;
389             }
390
391             std::string::size_type length = end_pos - pos - impl_section.size();
392
393             auto trim = [](const std::string& str) {
394                 size_t first = str.find_first_not_of(' ');
395                 if (std::string::npos == first) {
396                     return str;
397                 }
398                 size_t last = str.find_last_not_of(' ');
399                 return str.substr(first, (last - first + 1));
400             };
401             std::string tmp = trim(info.substr(pos + impl_section.size(), length));
402
403             return tmp.length() > 1 ? tmp : def_implementation;
404         };
405
406         // Parse primitive info and extract implementation name.
407         for (auto& id : m_env.profilingIDs) {
408             std::string prim_info = "";
409             try {
410                 prim_info = m_env.network->get_primitive_info(id);
411             } catch (std::exception& e) { }
412
413             implementationsMap.insert({id, extractImplementationFromInfo(prim_info)});
414         }
415     }
416 }
417
418 void CLDNNInferRequest::execAndParse() {
419     auto networkOutputs = m_env.network->execute();
420
421     // Collect outputs as requested by the model
422     for (auto& no : _networkOutputs) {
423         std::string outputID = outputsMap[no.first];
424         auto outputMemory = networkOutputs.at(outputID).get_memory();
425         Blob::Ptr bptr = _outputs[no.first];
426
427         auto out_ptr = outputMemory.pointer<uint8_t>();
428         auto blob_ptr = bptr->buffer().as<uint8_t*>();
429
430         // If Async API is used, copy of output blobs is not needed, unless SetBlob function was called.
431         // But in the case when old API is used we have to copy data to memory provided by user.
432         if (blob_ptr != &out_ptr[0]) {
433             copyOutputData(outputMemory, bptr);
434         }
435     }
436
437     // finally collect profiling info
438     if (m_useProfiling) {
439         std::map<cldnn::primitive_id, cldnn::event> executedPrimitives = m_env.network->get_executed_primitives();
440         auto allPrimitives = m_env.network->get_all_primitives();
441
442         // Get profiling info for all layers
443         for (auto &profiledID : m_env.profilingIDs) {
444             std::string impl = implementationsMap.at(profiledID);
445             impl.copy(m_env.perfMap[profiledID].exec_type, impl.length());
446
447             // Change status if layer wasn't executed by cldnn engine
448             if (executedPrimitives.find(profiledID) == executedPrimitives.end()) {
449                 if (allPrimitives.find(profiledID) != allPrimitives.end() &&
450                     allPrimitives.at(profiledID) == "_optimized_") {
451                     // Layer was marked as optimized by cldnn
452                     m_env.perfMap[profiledID].status = InferenceEngineProfileInfo::OPTIMIZED_OUT;
453                 } else {
454                     // Layer wasn't run for some reason
455                     m_env.perfMap[profiledID].status = InferenceEngineProfileInfo::NOT_RUN;
456                 }
457                 m_env.perfMap[profiledID].cpu_uSec = m_env.perfMap[profiledID].realTime_uSec = 0;
458                 continue;
459             }
460
461             auto event = executedPrimitives.at(profiledID);
462             executedPrimitives.erase(profiledID);
463
464             cldnn::instrumentation::profiling_info cldnnInfo{profiledID, event.get_profiling_info()};
465
466             // Collect timings
467             for (auto &interval : cldnnInfo.intervals) {
468                 using duration_t = std::chrono::duration<long long, std::chrono::microseconds::period>;
469                 auto count = std::chrono::duration_cast<duration_t>(interval.value->value()).count();
470
471                 if (interval.name == "submission") {
472                     m_env.perfMap[profiledID].cpu_uSec = count;
473                 } else if (interval.name == "executing") {
474                     m_env.perfMap[profiledID].realTime_uSec = count;
475                 } else if (interval.name == "duration") {  // "duration" is used for CPU layers
476                     m_env.perfMap[profiledID].cpu_uSec = count;
477                     static const std::string cpuExecType("CPU");
478                     memset(m_env.perfMap[profiledID].exec_type, 0, sizeof(m_env.perfMap[profiledID].exec_type));
479                     cpuExecType.copy(m_env.perfMap[profiledID].exec_type,
480                         cpuExecType.length());  // Override execType as CPU
481                 }
482             }
483         }
484     }
485 }
486
487 void CLDNNInferRequest::execAndParseDyn() {
488     std::vector<std::map<cldnn::primitive_id, cldnn::network_output>> networkOutputs(m_env.m_bv_sz);
489
490     // set up exection and put all graphs into driver queue
491     for (unsigned nb = 0; nb < m_env.m_bv_sz; nb++) {
492         unsigned int mask = 1 << nb;
493
494         if (m_curBatch & mask) {
495             networkOutputs[nb] = m_env.batchNetworks[nb]->execute();
496         }
497     }
498
499     // now try to get execution results
500     for (unsigned nb = 0; nb < m_env.m_bv_sz; nb++) {
501         unsigned int mask = 1 << nb;
502
503         if (m_curBatch & mask) {
504             for (auto& no : _networkOutputs) {
505                 std::string outputID = no.first;
506                 while ((m_env.primitiveIDs.find(outputID) != m_env.primitiveIDs.end()) &&
507                     (m_env.primitiveIDs.at(outputID) != outputID)) {
508                     outputID = m_env.primitiveIDs.at(outputID);
509                 }
510
511                 auto outputMemory = networkOutputs[nb].at(outputID).get_memory();
512                 Blob::Ptr bptr = _outputs[no.first];
513
514                 copyOutputData(outputMemory, bptr, &batchOutputs[no.first][nb]);
515             }
516         }
517     }
518 }
519
520 void CLDNNInferRequest::InferImpl() {
521     IE_PROFILING_AUTO_SCOPE(CLDNN_INFER)
522
523     // execute input pre-processing.
524     execDataPreprocessing(_inputs);
525
526     for (auto &item : _inputs) {
527         if (m_env.m_max_batch > 1) {
528             PrepareInputDyn(item.first, *item.second);
529         } else {
530             PrepareInput(item.first, *item.second);
531         }
532     }
533
534     // The actual inference
535     if (m_env.m_max_batch > 1) {
536         execAndParseDyn();
537     } else {
538         execAndParse();
539     }
540 }
541
542 void CLDNNInferRequest::GetPerformanceCounts(
543         std::map<std::string, InferenceEngineProfileInfo> &perfMap) const {
544     if (!m_useProfiling) {
545         THROW_IE_EXCEPTION << "Performance counters were not enabled";
546     } else {
547         perfMap = m_env.perfMap;
548     }
549 }
550
551 void CLDNNInferRequest::PrepareInput(const cldnn::primitive_id &inputName, const Blob &inputBlob) {
552     // Get input layout
553     if (m_env.inputLayouts.find(inputName) == m_env.inputLayouts.end()) {
554         THROW_IE_EXCEPTION << "Input name mismatch.";
555     }
556     auto inputLayout = m_env.inputLayouts.at(inputName);
557     auto is_same_buffer = [](const Blob& blob, const cldnn::memory& memory) -> bool {
558         const std::string str_not_allocated("Input data was not allocated.");
559         cldnn::pointer<const uint8_t> ptr = memory.pointer<const uint8_t>();
560         const uint8_t* blob_ptr = blob.cbuffer().as<const uint8_t*>();
561         const uint8_t* mem_ptr = ptr.data();
562         if (blob_ptr == nullptr || mem_ptr == nullptr) {
563             THROW_IE_EXCEPTION << str_not_allocated;
564         }
565         return (blob_ptr == mem_ptr) && (blob.byteSize() == memory.size());
566     };
567
568     const cldnn::memory& memory = inputsMemory.at(inputName);
569     if (inputBlob.precision() == Precision::I16) {
570         // clDNN doesn't support I16 input precision, so we always have to convert input data to fp32 precision
571         const cldnn::memory& fp32_mem = inputsMemory.at(inputName+fp32_suffix);
572         cldnn::pointer<float> ptr = fp32_mem.pointer<float>();
573         InferenceEngine::copyToFloat<int16_t>(ptr.data(), &inputBlob);
574         m_env.network->set_input_data(inputName, fp32_mem);
575     } else if (is_same_buffer(inputBlob, memory)) {
576         // If input memory was allocated by cldnn engine and wasn't overwritten by user set_input_data method won't copy input data.
577         switch (inputBlob.precision()) {
578             case Precision::FP32:
579             case Precision::FP16:
580             case Precision::U8: {
581                 m_env.network->set_input_data(inputName, memory);
582                 break;
583             }
584             default:
585                 THROW_IE_EXCEPTION << "Unsupported input precision " << inputBlob.precision();
586         }
587     } else {
588         // Otherwise, we have to attach to user memory and then copy the data.
589         copyInputData(m_env.network, inputName, inputLayout, inputBlob);
590     }
591 }
592
593 void CLDNNInferRequest::PrepareInputDyn(const cldnn::primitive_id &inputName, const Blob &inputBlob) {
594     // now try to get execution results
595     for (unsigned nb = 0; nb < m_env.m_bv_sz; nb++) {
596         unsigned int mask = 1 << nb;
597
598         if (m_curBatch & mask) {
599             auto inputLayout = m_env.inputLayouts.at(inputName);
600             inputLayout.size.batch[0] = mask;
601             copyInputData(m_env.batchNetworks[nb], inputName, inputLayout, inputBlob, &batchInputs[inputName][nb]);
602         }
603     }
604 }
605
606 };  // namespace CLDNNPlugin