1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
15 #include <cpp/ie_cnn_network.h>
16 #include <description_buffer.hpp>
18 #include <cpp_interfaces/base/ie_plugin_base.hpp>
19 #include "ie_plugin.hpp"
20 #include "ie_plugin_config.hpp"
21 #include "details/caseless.hpp"
22 #include <details/ie_cnn_network_tools.h>
27 #include "cldnn_engine.h"
28 #include "cldnn_graph.h"
29 #include "cldnn_custom_layer.h"
35 using InferenceEngine::DescriptionBuffer;
36 using InferenceEngine::TBlob;
37 using InferenceEngine::Blob;
38 using namespace InferenceEngine;
39 using namespace details;
41 namespace CLDNNPlugin {
43 struct clDNNEngine::impl {
44 CLDNNGraph::Config m_config;
47 clDNNEngine::clDNNEngine() {
50 // locate global custom kernel config
51 // and auto-load kernels from it
53 CHAR mpath[MAX_PATH + 1];
55 GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
56 (LPCSTR)CLDNNCustomLayer::LoadFromFile,
58 GetModuleFileName(nModule, mpath, sizeof(mpath));
61 dladdr(reinterpret_cast<void *>(CLDNNCustomLayer::LoadFromFile), &dl_info);
62 const char* mpath = dl_info.dli_fname;
64 std::string configFile(mpath);
65 std::size_t dir_split_pos = configFile.find_last_of("/\\");
66 std::string config_path;
68 if (dir_split_pos != std::string::npos) {
69 // path contains directory
70 config_path = configFile.substr(0, dir_split_pos);
72 config_path += "/cldnn_global_custom_kernels/cldnn_global_custom_kernels.xml";
73 CLDNNCustomLayer::LoadFromFile(config_path, _impl->m_config.customLayers, true);
76 clDNNEngine::~clDNNEngine() {
83 ExecutableNetworkInternal::Ptr clDNNEngine::LoadExeNetworkImpl(InferenceEngine::ICNNNetwork &network,
84 const std::map<std::string, std::string> &config) {
85 auto specifiedDevice = network.getTargetDevice();
86 auto supportedDevice = InferenceEngine::TargetDevice::eGPU;
87 if (specifiedDevice != InferenceEngine::TargetDevice::eDefault && specifiedDevice != supportedDevice) {
88 THROW_IE_EXCEPTION << "The plugin doesn't support target device: " << getDeviceName(specifiedDevice) << ".\n" <<
89 "Supported target device: " << getDeviceName(supportedDevice);
92 CLDNNGraph::Config conf = this->_impl->m_config;
93 conf.LoadFromMap(config);
95 // verification of supported input
96 InferenceEngine::InputsDataMap _networkInputs;
97 network.getInputsInfo(_networkInputs);
98 for (auto ii : _networkInputs) {
99 auto input_precision = ii.second->getInputPrecision();
100 if (input_precision != InferenceEngine::Precision::FP16 && input_precision != InferenceEngine::Precision::I16
101 && input_precision != InferenceEngine::Precision::FP32 && input_precision != InferenceEngine::Precision::U8) {
102 THROW_IE_EXCEPTION << NOT_IMPLEMENTED_str
103 << "Input image format " << input_precision << " is not supported yet...";
106 // todo: handle input precision differently - per input and not one per network...
109 if (conf.enableDynamicBatch) {
110 max_batch = network.getBatchSize();
113 return std::make_shared<CLDNNGraph>(network, conf, max_batch);
116 INFERENCE_PLUGIN_API(StatusCode) CreatePluginEngine(IInferencePlugin *&plugin, ResponseDesc *resp) noexcept {
118 plugin = make_ie_compatible_plugin(
121 "clDNNPlugin"}, std::make_shared<clDNNEngine>());
124 catch (std::exception &ex) {
125 return DescriptionBuffer(GENERAL_ERROR, resp) << ex.what();
129 void clDNNEngine::SetConfig(const std::map<std::string, std::string> &config) {
130 _impl->m_config.LoadFromMap(config);
133 void clDNNEngine::QueryNetwork(const ICNNNetwork& network, QueryNetworkResult& res) const {
134 QueryNetwork(network, {}, res);
137 void clDNNEngine::QueryNetwork(const ICNNNetwork& network, const std::map<std::string, std::string>& config, QueryNetworkResult& res) const {
138 std::vector <CNNLayer::Ptr> concats;
139 std::vector <CNNLayer::Ptr> nextLayerDependent;
141 std::vector<CNNLayerPtr> sortedLayers = CNNNetSortTopologically(network);
142 for (auto layer : sortedLayers) {
143 if (CaselessEq<std::string>()(layer->type, "DetectionOutput")) {
144 } else if (CaselessEq<std::string>()(layer->type, "PriorBox")) {
145 } else if (CaselessEq<std::string>()(layer->type, "Proposal")) {
146 } else if (CaselessEq<std::string>()(layer->type, "SimplerNMS")) {
147 } else if (CaselessEq<std::string>()(layer->type, "Concat")) {
148 concats.push_back(layer);
149 } else if (CaselessEq<std::string>()(layer->type, "reshape")) {
150 nextLayerDependent.push_back(layer);
151 } else if (CaselessEq<std::string>()(layer->type, "permute")) {
152 nextLayerDependent.push_back(layer);
153 } else if (CaselessEq<std::string>()(layer->type, "Const")) {
154 nextLayerDependent.push_back(layer);
155 } else if (CLDNNGraph::IsLayerSupported(layer->type)) {
156 res.supportedLayers.insert(layer->name);
160 // evaluation of concats - if all parent layers are supported, only in this case we
161 // will mark concat as a supported for GPU
162 for (const auto &concat : concats) {
163 // take all parrents.
164 bool supported = true;
165 for (DataWeakPtr insData : concat->insData) {
166 CNNLayerPtr prev = insData.lock()->getCreatorLayer().lock();
167 // verify if previous layer is not supported or if it in the list of not defined layers yet
168 // not defined layers are treated as layers which will be assigned to GPU if next layer is assigned to GPU
169 if (res.supportedLayers.find(prev->name) == res.supportedLayers.end()
170 && std::find(nextLayerDependent.begin(), nextLayerDependent.end(), prev) == nextLayerDependent.end()) {
175 res.supportedLayers.insert(concat->name);
178 // evaluation of constant blobs - if all consumers are on GPU,
179 // then leave it on GPU, else - move to other device
180 for (auto cnl = nextLayerDependent.rbegin();
181 cnl != nextLayerDependent.rend();
183 bool supported = true;
184 for (DataPtr out : (*cnl)->outData) {
185 for (auto ol : out->inputTo) {
186 if (res.supportedLayers.find(ol.second->name) == res.supportedLayers.end()) {
191 std::cout << (*cnl)->name << " is " << (supported ? "GPU" : "CPU") << std::endl;
194 res.supportedLayers.insert((*cnl)->name);
199 }; // namespace CLDNNPlugin