Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / thirdparty / clDNN / src / cldnn.cpp
1 /*
2 // Copyright (c) 2016-2019 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16
17 ///////////////////////////////////////////////////////////////////////////////////////////////////
18 #include "api/C/cldnn.h"
19 #include "api_impl.h"
20 #include "engine_impl.h"
21 #include "topology_impl.h"
22 #include "program_impl.h"
23 #include "primitive_type.h"
24 #include "network_impl.h"
25 #include "memory_impl.h"
26 #include "primitive_inst.h"
27
28 namespace cldnn {
29     last_err& last_err::instance()
30     {
31         thread_local static last_err _instance;
32         return _instance;
33     }
34 }
35
36 #define SHOULD_NOT_BE_NULL(arg, msg_prefix) \
37     if(arg == nullptr) \
38         throw std::invalid_argument( std::string(msg_prefix)  + " should not be null.");
39 #define SHOULD_NOT_EQUAL_0(arg, msg_prefix) \
40     if(arg == 0) \
41         throw std::invalid_argument( std::string(msg_prefix)  + " should not equals 0.");
42
43 extern "C"
44 {
45
46 #ifndef CLDNN_VERSION_MAJOR
47     #define CLDNN_VERSION_MAJOR (0)
48 #endif
49
50 #ifndef CLDNN_VERSION_MINOR
51     #define CLDNN_VERSION_MINOR (0)
52 #endif
53
54 #ifndef CLDNN_VERSION_BUILD
55     #define CLDNN_VERSION_BUILD (0)
56 #endif
57
58 #ifndef CLDNN_VERSION_REVISION
59     #define CLDNN_VERSION_REVISION (0)
60 #endif
61
62 cldnn_version cldnn_get_version(cldnn_status* status)
63 {
64     return exception_handler<cldnn_version>(CLDNN_ERROR, status, {}, []() -> cldnn_version
65     {
66         return { CLDNN_VERSION_MAJOR, CLDNN_VERSION_MINOR, CLDNN_VERSION_BUILD, CLDNN_VERSION_REVISION };
67     });
68 }
69
70
71 cldnn_topology cldnn_create_topology(cldnn_status* status)
72 {
73     return exception_handler<cldnn_topology>(CLDNN_ERROR, status, nullptr, [&]()
74     {
75         return api_cast(new cldnn::topology_impl());
76     });
77 }
78
79 void cldnn_add_primitive(cldnn_topology topology, const CLDNN_PRIMITIVE_DESC(primitive)* dto, cldnn_status* status)
80 {
81     return exception_handler(CLDNN_ERROR, status, [&]()
82     {
83         SHOULD_NOT_BE_NULL(topology,           "Topology");
84         SHOULD_NOT_BE_NULL(dto,                "Primitive");
85         SHOULD_NOT_BE_NULL(dto->id,            "Primitive id");
86         SHOULD_NOT_BE_NULL(dto->type,          "Primitive type");
87         api_cast(topology)->add(dto->type->from_dto(dto));
88     });
89 }
90
91 void cldnn_change_input_layout(cldnn_topology topology, cldnn_primitive_id id, cldnn_layout new_layout, cldnn_status* status)
92 {
93     return exception_handler(CLDNN_ERROR, status, [&]()
94     {
95         SHOULD_NOT_BE_NULL(topology, "Topology");
96         SHOULD_NOT_BE_NULL(id, "Input layout id");
97         if (new_layout.format < cldnn_format_any || new_layout.format >= cldnn_format_format_num)
98             throw std::invalid_argument("Unknown format of layout.");
99         if (new_layout.data_type != cldnn_data_type::cldnn_f16 &&
100             new_layout.data_type != cldnn_data_type::cldnn_f32 &&
101             new_layout.data_type != cldnn_data_type::cldnn_i8 &&
102             new_layout.data_type != cldnn_data_type::cldnn_u8 &&
103             new_layout.data_type != cldnn_data_type::cldnn_i32 &&
104             new_layout.data_type != cldnn_data_type::cldnn_i64)
105             throw std::invalid_argument("Unknown data_type of layout.");
106         api_cast(topology)->change_input_layout(id, new_layout);
107     });
108 }
109
110 static void primitive_id_vector_to_char_array(
111     char* names,
112     size_t size,
113     size_t* size_ret,
114     cldnn_status* status,
115     const std::vector<primitive_id>& vec)
116 {
117     *size_ret = std::accumulate(
118         std::begin(vec),
119         std::end(vec),
120         size_t(1), // final zero symbol
121         [](size_t acc, const cldnn::primitive_id& id)
122     {
123         return acc + id.size() + 1; // plus zero symbol
124     });
125
126     if (size < *size_ret)
127     {
128         if (status) *status = CLDNN_INVALID_ARG;
129         return;
130     }
131
132     size_t i = 0;
133     for (auto& id : vec)
134     {
135         // workaround for Microsoft VC++
136 #if defined _MSC_VER
137 #pragma warning(push)
138 #pragma warning(disable: 4996)
139 #endif
140         i += id.copy(names + i, size - i - 2);
141 #if defined _MSC_VER
142 #pragma warning(pop)
143 #endif
144         names[i++] = 0; // plus zero symbol
145         assert(i < size);
146     }
147     names[i] = 0; // final zero symbol
148 }
149
150 void cldnn_get_primitive_ids(cldnn_topology topology, char* ids, size_t size, size_t* size_ret, cldnn_status* status)
151 {
152     return exception_handler(CLDNN_ERROR, status, [&]()
153     {
154         SHOULD_NOT_BE_NULL(topology, "Topology");
155         auto ids_size = api_cast(topology)->get_primitives().size();
156         SHOULD_NOT_EQUAL_0(ids_size, "Primitives number");
157         auto&& primitives_ids = api_cast(topology)->get_primitives_id();
158         primitive_id_vector_to_char_array(ids, size, size_ret, status, primitives_ids);
159     });
160 }
161
162 void cldnn_retain_topology(cldnn_topology topology, cldnn_status* status)
163 {
164     return exception_handler(CLDNN_ERROR, status, [&]()
165     {
166         SHOULD_NOT_BE_NULL(topology, "Topology");
167         api_cast(topology)->add_ref();
168     });
169 }
170 void cldnn_release_topology(cldnn_topology topology, cldnn_status* status)
171 {
172     return exception_handler(CLDNN_ERROR, status, [&]()
173     {
174         SHOULD_NOT_BE_NULL(topology, "Topology");
175         api_cast(topology)->release();
176     });
177 }
178
179 uint32_t cldnn_get_engine_count(/*cldnn_engine_type*/ int32_t type, cldnn_status* status)
180 {
181     if (type == cldnn_engine_type::cldnn_engine_ocl)
182     {
183         if (status) *status = CLDNN_SUCCESS;
184         return 1;
185     }
186     else
187     {
188         if (status) *status = CLDNN_DEVICE_ERROR;
189         return 0;
190     }
191 }
192
193 void cldnn_release_pending_memory(cldnn_engine engine, cldnn_status* status)
194 {
195     return exception_handler(CLDNN_ERROR, status, [&]()
196     {
197         SHOULD_NOT_BE_NULL(engine, "engine");
198         api_cast(engine)->release_pending_memory();
199     });
200 }
201
202 cldnn_engine cldnn_create_engine(/*cldnn_engine_type*/ int32_t type, uint32_t engine_num, const cldnn_engine_configuration* configuration, cldnn_status* status)
203 {
204     if (engine_num > 0 || (type != cldnn_engine_type::cldnn_engine_ocl))
205     {
206         if (status)
207             *status = CLDNN_DEVICE_ERROR;
208         return nullptr;
209     }
210
211     return exception_handler<cldnn_engine>(CLDNN_ERROR, status, nullptr, [&]()
212     {
213         return api_cast(new cldnn::engine_impl(configuration ? cldnn::engine_configuration(*configuration) : cldnn::engine_configuration()));
214     });
215 }
216
217 void cldnn_retain_engine(cldnn_engine engine, cldnn_status* status)
218 {
219         exception_handler(CLDNN_ERROR, status, [&]()
220         {
221             SHOULD_NOT_BE_NULL(engine, "Engine");
222             api_cast(engine)->add_ref();
223         });
224 }
225
226 void cldnn_release_engine(cldnn_engine engine, cldnn_status* status)
227 {
228         exception_handler(CLDNN_ERROR, status, [&]()
229         {
230             SHOULD_NOT_BE_NULL(engine, "Engine");
231             api_cast(engine)->release();
232         });
233 }
234
235 cldnn_engine_info cldnn_get_engine_info(cldnn_engine engine, cldnn_status* status)
236 {
237     return exception_handler<cldnn_engine_info>(CLDNN_ERROR, status, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, [&]() -> cldnn_engine_info
238     {
239         SHOULD_NOT_BE_NULL(engine, "Engine");
240         auto info = api_cast(engine)->get_engine_info();
241         return
242         {
243             info.cores_count,
244             info.core_frequency,
245             info.max_work_group_size,
246             info.max_local_mem_size,
247             info.max_global_mem_size,
248             info.max_alloc_mem_size,
249             info.max_image2d_width,
250             info.max_image2d_height,
251             info.supports_fp16,
252             info.supports_fp16_denorms,
253             info.supports_subgroups_short,
254             info.supports_image
255        };
256     });
257 }
258
259 /*cldnn_engine_type*/ int32_t cldnn_get_engine_type(cldnn_engine engine, cldnn_status* status)
260 {
261     return exception_handler<int32_t>(CLDNN_ERROR, status, cldnn_engine_ocl, [&]()
262     {
263         SHOULD_NOT_BE_NULL(engine, "Engine");
264         return static_cast<int32_t>(api_cast(engine)->type());
265     });
266 }
267
268 int64_t cldnn_get_max_used_device_memory_size(cldnn_engine engine, cldnn_status* status)
269 {
270     return exception_handler<int32_t>(CLDNN_ERROR, status, cldnn_engine_ocl, [&]()
271     {
272         SHOULD_NOT_BE_NULL(engine, "Engine");
273         return static_cast<int32_t>(api_cast(engine)->get_max_used_device_memory());
274     });
275 }
276
277 int64_t cldnn_get_temp_used_device_memory_size(cldnn_engine engine, cldnn_status* status)
278 {
279     return exception_handler<int32_t>(CLDNN_ERROR, status, cldnn_engine_ocl, [&]()
280     {
281         SHOULD_NOT_BE_NULL(engine, "Engine");
282         return static_cast<int32_t>(api_cast(engine)->get_used_device_memory());
283     });
284 }
285
286 cldnn_event cldnn_create_user_event(cldnn_engine engine, cldnn_status* status)
287 {
288     return exception_handler<cldnn_event>(CLDNN_ERROR, status, nullptr, [&]()
289     {
290         SHOULD_NOT_BE_NULL(engine, "Engine");
291         event_impl* e = api_cast(engine)->create_user_event().detach();
292         return api_cast(e);
293     });
294 }
295
296 CLDNN_API int32_t cldnn_is_user_event(cldnn_event event, cldnn_status * status)
297 {
298     return exception_handler<int32_t>(CLDNN_ERROR, status, 0, [&]()
299     {
300         SHOULD_NOT_BE_NULL(event, "Event");
301         auto user_ev = dynamic_cast<user_event*>(api_cast(event));
302         return (user_ev != nullptr);
303     });
304 }
305
306 void cldnn_retain_event(cldnn_event event, cldnn_status* status)
307 {
308
309     exception_handler(CLDNN_ERROR, status, [&]()
310     {
311         SHOULD_NOT_BE_NULL(event, "Event");
312         api_cast(event)->add_ref();
313     });
314 }
315
316 void cldnn_release_event(cldnn_event event, cldnn_status* status)
317 {
318     exception_handler(CLDNN_ERROR, status, [&]()
319     {
320         SHOULD_NOT_BE_NULL(event, "Event");
321         api_cast(event)->release();
322     });
323 }
324
325 void cldnn_wait_for_event(cldnn_event event, cldnn_status* status)
326 {
327     exception_handler(CLDNN_ERROR, status, [&]()
328     {
329         SHOULD_NOT_BE_NULL(event, "Event");
330         api_cast(event)->wait();
331     });
332 }
333
334 void cldnn_set_event(cldnn_event event, cldnn_status* status)
335 {
336     exception_handler(CLDNN_ERROR, status, [&]()
337     {
338         SHOULD_NOT_BE_NULL(event, "Event");
339         if (auto user_ev = dynamic_cast<user_event*>(api_cast(event)))
340             user_ev->set();
341         else
342             throw std::invalid_argument("Event passed to cldnn_set_event should be an user event");
343     });
344 }
345
346 void cldnn_add_event_handler(cldnn_event event, cldnn_event_handler handler, void* param, cldnn_status* status)
347 {
348     exception_handler(CLDNN_ERROR, status, [&]()
349     {
350         SHOULD_NOT_BE_NULL(handler, "Handler");
351         SHOULD_NOT_BE_NULL(event,   "Event");
352         api_cast(event)->add_event_handler(handler, param);
353     });
354 }
355
356 void cldnn_get_event_profiling_info(cldnn_event event, cldnn_profiling_interval* profiling, size_t size, size_t* size_ret, cldnn_status* status)
357 {
358     exception_handler(CLDNN_ERROR, status, [&]()
359     {
360         SHOULD_NOT_BE_NULL(event, "Event");
361         if (!profiling && !size_ret)
362         {
363             if (status) *status = CLDNN_INVALID_ARG;
364             return;
365         }
366         auto& profiling_info = api_cast(event)->get_profiling_info();
367         if (size_ret)
368             *size_ret = profiling_info.size();
369         if(profiling != nullptr)
370         {
371             if (size != profiling_info.size())
372             {
373                 if (status) *status = CLDNN_INVALID_ARG;
374                 return;
375             }
376             size_t i = 0;
377             for (auto& info : profiling_info)
378             {
379                 profiling[i].name = info.name;
380                 profiling[i].nanoseconds = info.nanoseconds;
381                 ++i;
382             }
383         }
384     });
385 }
386
387 cldnn_program cldnn_build_program(cldnn_engine engine, cldnn_topology topology, cldnn_build_option* options, size_t options_num, cldnn_status* status)
388 {
389     return exception_handler<cldnn_program>(CLDNN_ERROR, status, nullptr, [&]()
390     {
391         SHOULD_NOT_BE_NULL(engine,   "Engine");
392         SHOULD_NOT_BE_NULL(topology, "Topology");
393         cldnn::build_options options_obj(cldnn::array_ref<cldnn_build_option>(options, options_num));
394
395         cldnn::program_impl* prog = api_cast(engine)->build_program(*api_cast(topology), options_obj).detach();
396         return api_cast(prog);
397     });
398 }
399
400 void cldnn_retain_program(cldnn_program program, cldnn_status* status)
401 {
402     exception_handler(CLDNN_ERROR, status, [&]()
403     {
404         SHOULD_NOT_BE_NULL(program, "Program");
405         api_cast(program)->add_ref();
406     });
407 }
408
409 void cldnn_release_program(cldnn_program program, cldnn_status* status)
410 {
411     exception_handler(CLDNN_ERROR, status, [&]()
412     {
413         SHOULD_NOT_BE_NULL(program, "Program");
414         api_cast(program)->release();
415     });
416 }
417
418 cldnn_network cldnn_allocate_network(cldnn_program program, cldnn_status* status)
419 {
420     return exception_handler<cldnn_network>(CLDNN_ERROR, status, nullptr, [&]()
421     {
422         SHOULD_NOT_BE_NULL(program, "Program");
423         network_impl* p = api_cast(program)->get_engine().allocate_network(*api_cast(program)).detach();
424         return api_cast(p);
425     });
426 }
427
428 cldnn_network cldnn_build_network(cldnn_engine engine, cldnn_topology topology, cldnn_build_option* options, size_t options_num, cldnn_status* status)
429 {
430     cldnn_program program = cldnn_build_program(engine, topology, options, options_num, status);
431     if (!program)
432         return nullptr;
433
434     cldnn_network network = cldnn_allocate_network(program, status);
435     cldnn_release_program(program, nullptr);
436     return network;
437 }
438 void cldnn_retain_network(cldnn_network network, cldnn_status* status)
439 {
440     exception_handler(CLDNN_ERROR, status, [&]()
441     {
442         SHOULD_NOT_BE_NULL(network, "Network");
443         api_cast(network)->add_ref();
444     });
445 }
446
447 void cldnn_release_network(cldnn_network network, cldnn_status* status)
448 {
449     exception_handler(CLDNN_ERROR, status, [&]()
450     {
451         SHOULD_NOT_BE_NULL(network, "Network");
452         api_cast(network)->release();
453     });
454 }
455
456 void cldnn_set_network_input(cldnn_network network, cldnn_primitive_id id, cldnn_memory mem, cldnn_status* status)
457 {
458     exception_handler(CLDNN_ERROR, status, [&]()
459     {
460         SHOULD_NOT_BE_NULL(mem, "Mem");
461         auto mem_size = api_cast(mem)->size();
462         SHOULD_NOT_BE_NULL(network,     "Network");
463         SHOULD_NOT_BE_NULL(id,          "Id");
464         SHOULD_NOT_EQUAL_0(mem_size,    "Memory size");
465         api_cast(network)->set_input_data(id, *api_cast(mem));
466     });
467 }
468
469 void cldnn_set_learning_rate(cldnn_network network, float lr, cldnn_status* status)
470 {
471     exception_handler(CLDNN_ERROR, status, [&]()
472     {
473         api_cast(network)->set_learning_rate(lr);
474     });
475 }
476
477 float cldnn_get_learning_rate(cldnn_network network, cldnn_status* status)
478 {
479     return exception_handler<float>(CLDNN_ERROR, status, 0, [&]()
480     {
481         return api_cast(network)->get_learning_rate();
482     });
483 }
484
485 cldnn_engine cldnn_get_network_engine(cldnn_network network, cldnn_status* status)
486 {
487     return exception_handler<cldnn_engine>(CLDNN_ERROR, status, nullptr, [&]()
488     {
489         SHOULD_NOT_BE_NULL(network, "Network");
490         refcounted_obj_ptr<cldnn::engine_impl> ptr{&api_cast(network)->get_engine()};
491         return api_cast(ptr.detach());
492     });
493 }
494
495 cldnn_program cldnn_get_network_program(cldnn_network network, cldnn_status* status)
496 {
497     return exception_handler<cldnn_program>(CLDNN_ERROR, status, nullptr, [&]()
498     {
499         SHOULD_NOT_BE_NULL(network, "Network");
500         refcounted_obj_ptr<cldnn::program_impl> ptr{const_cast<cldnn::program_impl*>(&api_cast(network)->get_program())};
501         return api_cast(ptr.detach());
502     });
503 }
504
505 void cldnn_get_primitive_info(cldnn_network network, cldnn_primitive_id prim_id, char* info, size_t size, size_t* size_ret, cldnn_status* status)
506 {
507     return exception_handler(CLDNN_ERROR, status, [&]()
508     {
509         SHOULD_NOT_BE_NULL(network, "Network");
510         const auto& prim_info = api_cast(network)->get_primitive_info(prim_id);
511         *size_ret = prim_info.size()+1;
512
513         if (size < *size_ret)
514         {
515             if (status) *status = CLDNN_INVALID_ARG;
516             return;
517         }
518
519         size_t i = 0;
520         for (const auto c : prim_info)
521         {
522             info[i++] = c;
523             assert(i < size);
524         }
525         info[i] = 0; // final zero symbol
526     });
527 }
528
529 void cldnn_get_network_output_names(cldnn_network network, char* names, size_t size, size_t* size_ret, cldnn_status* status)
530 {
531     exception_handler(CLDNN_ERROR, status, [&]()
532     {
533         SHOULD_NOT_BE_NULL(network, "Network");
534         auto&& output_ids = api_cast(network)->get_output_ids();
535         SHOULD_NOT_EQUAL_0(output_ids.size(), "Output size");
536         primitive_id_vector_to_char_array(names, size, size_ret, status, output_ids);
537     });
538 }
539
540 void cldnn_get_network_executed_primitive_names(cldnn_network network, char* names, size_t size, size_t* size_ret, cldnn_status* status)
541 {
542     exception_handler(CLDNN_ERROR, status, [&]()
543     {
544         SHOULD_NOT_BE_NULL(network, "Network");
545         auto&& primitive_ids = api_cast(network)->get_executed_primitive_ids();
546         SHOULD_NOT_EQUAL_0(primitive_ids.size(), "Primitives size");
547         primitive_id_vector_to_char_array(names, size, size_ret, status, primitive_ids);
548     });
549 }
550
551 void cldnn_get_network_all_primitive_names(cldnn_network network, char* names, size_t size, size_t* size_ret, cldnn_status* status)
552 {
553     exception_handler(CLDNN_ERROR, status, [&]()
554     {
555         SHOULD_NOT_BE_NULL(network, "Network");
556         auto&& primitive_ids = api_cast(network)->get_all_primitive_ids();
557         SHOULD_NOT_EQUAL_0(primitive_ids.size(), "Primitives size");
558         primitive_id_vector_to_char_array(names, size, size_ret, status, primitive_ids);
559     });
560 }
561
562 void cldnn_get_network_all_primitive_org_names(cldnn_network network, char* names, size_t size, size_t* size_ret, cldnn_status* status)
563 {
564     exception_handler(CLDNN_ERROR, status, [&]()
565     {
566         SHOULD_NOT_BE_NULL(network, "Network");
567         auto&& primitive_ids = api_cast(network)->get_all_primitive_org_ids();
568         SHOULD_NOT_EQUAL_0(primitive_ids.size(), "Primitives size");
569         primitive_id_vector_to_char_array(names, size, size_ret, status, primitive_ids);
570     });
571 }
572
573 void cldnn_execute_network(cldnn_network network, cldnn_event* dependencies, size_t deps_num, cldnn_status* status)
574 {
575     exception_handler(CLDNN_ERROR, status, [&]()
576     {
577         SHOULD_NOT_BE_NULL(network, "Network");
578         std::vector<cldnn::refcounted_obj_ptr<cldnn::event_impl>> deps;
579         deps.reserve(deps_num);
580         for(size_t i = 0; i < deps_num; i++)
581         {
582             deps.emplace_back(api_cast(dependencies[i]));
583         }
584
585         api_cast(network)->execute(deps);
586     });
587 }
588
589 cldnn_network_output cldnn_get_network_output(cldnn_network network, const char* name, cldnn_status* status)
590 {
591     cldnn_network_output error_result = { nullptr, nullptr };
592     return exception_handler<cldnn_network_output>(CLDNN_ERROR, status, error_result, [&]() -> cldnn_network_output
593     {
594         SHOULD_NOT_BE_NULL(network, "Network");
595         SHOULD_NOT_BE_NULL(name,    "ID of primitive");
596         cldnn::primitive_id id(name);
597         auto event = api_cast(network)->get_primitive_event(id);
598         auto& mem_result = api_cast(network)->get_primitive(id)->output_memory();
599         refcounted_obj_ptr<cldnn::memory_impl> mem_ptr{&mem_result};
600         return{
601                 api_cast(event.detach()),
602                 api_cast(mem_ptr.detach())
603         };
604     });
605 }
606
607 cldnn_memory cldnn_get_network_output_memory(cldnn_network network, const char* name, cldnn_status* status)
608 {
609     cldnn_memory error_result =  nullptr;
610     return exception_handler<cldnn_memory>(CLDNN_ERROR, status, error_result, [&]() -> cldnn_memory
611     {
612         SHOULD_NOT_BE_NULL(network, "Network");
613         SHOULD_NOT_BE_NULL(name, "ID of primitive");
614         cldnn::primitive_id id(name);
615         auto& mem_result = api_cast(network)->get_primitive(id)->output_memory();
616         refcounted_obj_ptr<cldnn::memory_impl> mem_ptr{&mem_result};
617         return api_cast(mem_ptr.detach());
618     });
619 }
620
621 cldnn_event cldnn_get_network_output_event(cldnn_network network, const char* name, cldnn_status* status)
622 {
623     cldnn_event error_result = nullptr;
624     return exception_handler<cldnn_event>(CLDNN_ERROR, status, error_result, [&]() -> cldnn_event
625     {
626         SHOULD_NOT_BE_NULL(network, "Network");
627         SHOULD_NOT_BE_NULL(name, "ID of primitive");
628         cldnn::primitive_id id(name);
629         auto event = api_cast(network)->get_primitive_event(id);
630         return api_cast(event.detach());
631     });
632 }
633
634 cldnn_memory cldnn_allocate_memory(cldnn_engine engine, cldnn_layout layout, cldnn_status* status)
635 {
636     return exception_handler<cldnn_memory>(CLDNN_ERROR, status, nullptr, [&]()
637     {
638         SHOULD_NOT_BE_NULL(engine, "Engine");
639         if (layout.format < cldnn_format_any || layout.format >= cldnn_format_format_num)
640             throw std::invalid_argument("Unknown format of layout.");
641         if (layout.data_type != cldnn_data_type::cldnn_f16 &&
642             layout.data_type != cldnn_data_type::cldnn_f32 &&
643             layout.data_type != cldnn_data_type::cldnn_i8 &&
644             layout.data_type != cldnn_data_type::cldnn_u8 &&
645             layout.data_type != cldnn_data_type::cldnn_i32 &&
646             layout.data_type != cldnn_data_type::cldnn_i64)
647             throw std::invalid_argument("Unknown data_type of layout.");
648
649         cldnn::memory_impl* mem_ptr = api_cast(engine)->allocate_memory(layout).detach();
650         return api_cast(mem_ptr);
651     });
652 }
653
654 cldnn_memory cldnn_attach_memory(cldnn_layout layout, void* pointer, size_t size, cldnn_status* status)
655 {
656     return exception_handler<cldnn_memory>(CLDNN_ERROR, status, nullptr, [&]()
657     {
658         cldnn::layout layout_obj(layout);
659         if (layout_obj.bytes_count() > size)
660             throw std::invalid_argument("buffer size does not match layout size");
661         return api_cast(new cldnn::simple_attached_memory(layout_obj, pointer));
662     });
663 }
664
665 CLDNN_API int32_t cldnn_is_the_same_buffer(cldnn_memory mem1, cldnn_memory mem2, cldnn_status* status)
666 {
667     return static_cast<int32_t>(exception_handler<bool>(CLDNN_ERROR, status, false, [&]()
668     {
669         SHOULD_NOT_BE_NULL(mem1, "Memory");
670         SHOULD_NOT_BE_NULL(mem2, "Memory");
671
672         if (mem1 == mem2)
673             return true;
674
675         if (api_cast(mem1)->get_engine() != api_cast(mem2)->get_engine())
676             return false;
677
678         //memories were allocated by the user so just check if pointers match
679         if (!api_cast(mem1)->get_engine())
680             return api_cast(mem1)->lock() == api_cast(mem2)->lock();
681
682         //memories were allocated by the engine so let it decide whether they refer to the same buffer
683         return api_cast(mem1)->get_engine()->is_the_same_buffer(*api_cast(mem1), *api_cast(mem2));
684     }));
685 }
686
687 void cldnn_retain_memory(cldnn_memory memory, cldnn_status* status)
688 {
689     exception_handler(CLDNN_ERROR, status, [&]()
690     {
691         SHOULD_NOT_BE_NULL(memory, "Memory");
692         api_cast(memory)->add_ref();
693     });
694 }
695
696 void cldnn_release_memory(cldnn_memory memory, cldnn_status* status)
697 {
698     exception_handler(CLDNN_ERROR, status, [&]()
699     {
700         SHOULD_NOT_BE_NULL(memory, "Memory");
701         api_cast(memory)->release();
702     });
703 }
704
705 void* cldnn_lock_memory(cldnn_memory memory, cldnn_status* status)
706 {
707     return exception_handler<void*>(CLDNN_ERROR, status, nullptr, [&]()
708     {
709         SHOULD_NOT_BE_NULL(memory, "Memory");
710         return api_cast(memory)->lock();
711     });
712 }
713
714 void cldnn_unlock_memory(cldnn_memory memory, cldnn_status* status)
715 {
716     exception_handler(CLDNN_ERROR, status, [&]()
717     {
718         SHOULD_NOT_BE_NULL(memory, "Memory");
719         api_cast(memory)->unlock();
720     });
721 }
722
723 cldnn_layout cldnn_get_memory_layout(cldnn_memory memory, cldnn_status* status)
724 {
725     cldnn_layout error_result = cldnn::layout(cldnn::data_types::f32, cldnn::format::bfyx, {0, 0, 0, 0});
726
727     return exception_handler<cldnn_layout>(CLDNN_ERROR, status, error_result, [&]()
728     {
729         SHOULD_NOT_BE_NULL(memory, "Memory");
730         auto memory_size = api_cast(memory)->size();
731         SHOULD_NOT_EQUAL_0(memory_size, "Memory size");
732         return api_cast(memory)->get_layout();
733     });
734 }
735
736 cldnn_engine cldnn_get_memory_engine(cldnn_memory memory, cldnn_status* status)
737 {
738     return exception_handler<cldnn_engine>(CLDNN_ERROR, status, nullptr, [&]()
739     {
740         SHOULD_NOT_BE_NULL(memory, "Memory");
741         auto engine = api_cast(memory)->get_engine();
742         return api_cast(engine.detach());
743     });
744 }
745
746 const char* cldnn_get_last_error_message()
747 {
748     try {
749         return cldnn::last_err::instance().get_last_error_message().c_str();
750     }
751     catch (...)
752     {
753         return "Reading error message failed.";
754     }
755 }
756
757
758 CLDNN_API uint16_t cldnn_float_to_half(float value, cldnn_status* status)
759 {
760     return exception_handler<uint16_t>(CLDNN_ERROR, status, 0, [&]()
761     {
762         return cldnn::float_to_half(value);
763     });
764 }
765
766 CLDNN_API float cldnn_half_to_float(uint16_t value, cldnn_status* status)
767 {
768     return exception_handler<float>(CLDNN_ERROR, status, 0.0f, [&]()
769     {
770         return cldnn::half_to_float(value);
771     });
772 }
773
774 } /* extern "C" */
775
776 #define PRIMITIVE_TYPE_ID_CALL_IMPL(PType) \
777 namespace cldnn { primitive_type_id PType##_type_id(); }\
778 extern "C" CLDNN_API cldnn_primitive_type_id cldnn_##PType##_type_id(cldnn_status* status)\
779 {\
780     return exception_handler<cldnn_primitive_type_id>(CLDNN_ERROR, status, nullptr, []()\
781     {\
782         return cldnn::PType##_type_id();\
783     });\
784 }
785
786 PRIMITIVE_TYPE_ID_CALL_IMPL(activation)
787 PRIMITIVE_TYPE_ID_CALL_IMPL(activation_grad)
788 PRIMITIVE_TYPE_ID_CALL_IMPL(arg_max_min)
789 PRIMITIVE_TYPE_ID_CALL_IMPL(average_unpooling)
790 PRIMITIVE_TYPE_ID_CALL_IMPL(batch_norm)
791 PRIMITIVE_TYPE_ID_CALL_IMPL(batch_norm_grad)
792 PRIMITIVE_TYPE_ID_CALL_IMPL(border)
793 PRIMITIVE_TYPE_ID_CALL_IMPL(broadcast)
794 PRIMITIVE_TYPE_ID_CALL_IMPL(convolution)
795 PRIMITIVE_TYPE_ID_CALL_IMPL(crop)
796 PRIMITIVE_TYPE_ID_CALL_IMPL(data)
797 PRIMITIVE_TYPE_ID_CALL_IMPL(embed)
798 PRIMITIVE_TYPE_ID_CALL_IMPL(mutable_data)
799 PRIMITIVE_TYPE_ID_CALL_IMPL(deconvolution)
800 PRIMITIVE_TYPE_ID_CALL_IMPL(concatenation)
801 PRIMITIVE_TYPE_ID_CALL_IMPL(eltwise)
802 PRIMITIVE_TYPE_ID_CALL_IMPL(fully_connected)
803 PRIMITIVE_TYPE_ID_CALL_IMPL(fused_conv_bn_scale)
804 PRIMITIVE_TYPE_ID_CALL_IMPL(fused_conv_eltwise)
805 PRIMITIVE_TYPE_ID_CALL_IMPL(input_layout)
806 PRIMITIVE_TYPE_ID_CALL_IMPL(lookup_table)
807 PRIMITIVE_TYPE_ID_CALL_IMPL(lrn)
808 PRIMITIVE_TYPE_ID_CALL_IMPL(max_unpooling)
809 PRIMITIVE_TYPE_ID_CALL_IMPL(permute)
810 PRIMITIVE_TYPE_ID_CALL_IMPL(pooling)
811 PRIMITIVE_TYPE_ID_CALL_IMPL(reorder)
812 PRIMITIVE_TYPE_ID_CALL_IMPL(reshape)
813 PRIMITIVE_TYPE_ID_CALL_IMPL(scale)
814 PRIMITIVE_TYPE_ID_CALL_IMPL(scale_grad_input)
815 PRIMITIVE_TYPE_ID_CALL_IMPL(scale_grad_weights)
816 PRIMITIVE_TYPE_ID_CALL_IMPL(softmax)
817 PRIMITIVE_TYPE_ID_CALL_IMPL(region_yolo)
818 PRIMITIVE_TYPE_ID_CALL_IMPL(reorg_yolo)
819 PRIMITIVE_TYPE_ID_CALL_IMPL(proposal)
820 PRIMITIVE_TYPE_ID_CALL_IMPL(roi_pooling)
821 PRIMITIVE_TYPE_ID_CALL_IMPL(prior_box)
822 PRIMITIVE_TYPE_ID_CALL_IMPL(detection_output)
823 PRIMITIVE_TYPE_ID_CALL_IMPL(detection_output_sort)
824 PRIMITIVE_TYPE_ID_CALL_IMPL(normalize)
825 PRIMITIVE_TYPE_ID_CALL_IMPL(generic_layer)
826 PRIMITIVE_TYPE_ID_CALL_IMPL(custom_gpu_primitive)
827 PRIMITIVE_TYPE_ID_CALL_IMPL(split)
828 PRIMITIVE_TYPE_ID_CALL_IMPL(upsampling)
829 PRIMITIVE_TYPE_ID_CALL_IMPL(convolution_grad_weights)
830 PRIMITIVE_TYPE_ID_CALL_IMPL(apply_adam)
831 PRIMITIVE_TYPE_ID_CALL_IMPL(mvn)
832 PRIMITIVE_TYPE_ID_CALL_IMPL(fully_connected_grad_input)
833 PRIMITIVE_TYPE_ID_CALL_IMPL(fully_connected_grad_weights)
834 PRIMITIVE_TYPE_ID_CALL_IMPL(lstm)
835 PRIMITIVE_TYPE_ID_CALL_IMPL(lstm_gemm)
836 PRIMITIVE_TYPE_ID_CALL_IMPL(lstm_elt)
837 PRIMITIVE_TYPE_ID_CALL_IMPL(softmax_loss_grad)
838 PRIMITIVE_TYPE_ID_CALL_IMPL(tile)
839 PRIMITIVE_TYPE_ID_CALL_IMPL(gemm)
840 PRIMITIVE_TYPE_ID_CALL_IMPL(select)
841 PRIMITIVE_TYPE_ID_CALL_IMPL(index_select)
842 PRIMITIVE_TYPE_ID_CALL_IMPL(condition)
843 PRIMITIVE_TYPE_ID_CALL_IMPL(pyramid_roi_align)
844 PRIMITIVE_TYPE_ID_CALL_IMPL(contract)
845 PRIMITIVE_TYPE_ID_CALL_IMPL(one_hot)
846 PRIMITIVE_TYPE_ID_CALL_IMPL(gather)
847 PRIMITIVE_TYPE_ID_CALL_IMPL(depth_to_space)
848 PRIMITIVE_TYPE_ID_CALL_IMPL(shuffle_channels)
849 PRIMITIVE_TYPE_ID_CALL_IMPL(strided_slice)
850 PRIMITIVE_TYPE_ID_CALL_IMPL(reverse_sequence)