forked from openvinotoolkit/openvino
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplugin.cpp
316 lines (276 loc) · 13.3 KB
/
plugin.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
// clang-format off
#include "ie_metric_helpers.hpp"
#include "openvino/runtime/device_id_parser.hpp"
#include "plugin.hpp"
#include <memory>
#include <vector>
#include <map>
#include <string>
#include <utility>
#include <fstream>
#include <unordered_set>
#include "ie_plugin_config.hpp"
#include "executable_network.hpp"
#include "cpp_interfaces/interface/ie_internal_plugin_config.hpp"
#include "openvino/util/common_util.hpp"
#include "openvino/runtime/properties.hpp"
#include "internal_properties.hpp"
#include "openvino/util/common_util.hpp"
// clang-format on
using namespace InferenceEngine;
using namespace InferenceEngine::PluginConfigParams;
using namespace InferenceEngine::HeteroConfigParams;
using namespace HeteroPlugin;
namespace {
const std::vector<std::string>& getHeteroSupportedConfigKeys() {
static const std::vector<std::string> supported_configKeys = {HETERO_CONFIG_KEY(DUMP_GRAPH_DOT),
"TARGET_FALLBACK",
ov::device::priorities.name()};
return supported_configKeys;
}
const std::vector<std::string>& getHeteroDeviceSupportedConfigKeys() {
static const std::vector<std::string> supported_configKeys = {CONFIG_KEY(EXCLUSIVE_ASYNC_REQUESTS)};
return supported_configKeys;
}
std::vector<std::string> getSupportedConfigKeys() {
std::vector<std::string> supported_configKeys = getHeteroSupportedConfigKeys();
for (auto&& key : getHeteroDeviceSupportedConfigKeys())
supported_configKeys.emplace_back(key);
return supported_configKeys;
}
ov::AnyMap any_copy(const Configs& params) {
ov::AnyMap result;
for (auto&& value : params) {
result.emplace(value.first, value.second);
}
return result;
}
Configs any_copy(const ov::AnyMap& params) {
Configs result;
for (auto&& value : params) {
result.emplace(value.first, value.second.as<std::string>());
}
return result;
}
} // namespace
Engine::Engine() {
_pluginName = "HETERO";
_config[HETERO_CONFIG_KEY(DUMP_GRAPH_DOT)] = NO;
_device_config[CONFIG_KEY(EXCLUSIVE_ASYNC_REQUESTS)] = YES;
}
ParsedConfig<ov::AnyMap> Engine::MergeConfigs(const ov::AnyMap& user_config) const {
auto device_config = user_config;
auto hetero_config = _config;
// after API 1.0 removal, replace with the loop over getHeteroSupportedConfigKeys()
{
auto try_merge_property = [&](const std::string& property_name) -> bool {
auto property_it = device_config.find(property_name);
if (property_it != device_config.end()) {
// migrate HETERO property to hetero_config
hetero_config[property_it->first] = property_it->second.as<std::string>();
// and erase it from device_config
device_config.erase(property_it->first);
return true;
}
return false;
};
try_merge_property(HETERO_CONFIG_KEY(DUMP_GRAPH_DOT));
// if we have not found TARGET_FALLBACK in user_config, let's try to find device::priorities
// Note: we can have conflicts here like
// core.set_property(HETERO, TARGET_FALLBACK=MULTI,CPU)
// core.compile_model(HETERO, DEVICE_PRIORITIES=GPU.0,GPU.1)
// so, we need to check whether TARGET_FALLBACK was set before in set_property
// This check can be removed after API 1.0 is removed
if (!try_merge_property("TARGET_FALLBACK") && hetero_config.find("TARGET_FALLBACK") == hetero_config.end()) {
try_merge_property(ov::device::priorities.name());
}
}
// merge device_config settings
for (auto&& key : getHeteroDeviceSupportedConfigKeys()) {
auto user_config_it = user_config.find(key);
if (user_config_it != user_config.end()) {
device_config[user_config_it->first] = user_config_it->second;
}
}
return {hetero_config, device_config};
}
ParsedConfig<Configs> Engine::MergeConfigs(const Configs& user_config) const {
auto parsed_config = MergeConfigs(any_copy(user_config));
return {parsed_config.hetero_config, any_copy(parsed_config.device_config)};
}
std::string Engine::GetTargetFallback(const Configs& user_config, bool raise_exception) const {
return GetTargetFallback(any_copy(user_config), raise_exception);
}
std::string Engine::GetTargetFallback(const ov::AnyMap& user_config, bool raise_exception) const {
auto hetero_config = MergeConfigs(user_config).hetero_config;
auto it = hetero_config.find("TARGET_FALLBACK");
if (it == hetero_config.end()) {
it = hetero_config.find(ov::device::priorities.name());
}
if (it == hetero_config.end()) {
if (raise_exception)
IE_THROW() << "The '" << ov::device::priorities.name()
<< "' option was not defined for heterogeneous plugin";
return std::string("");
}
return it->second;
}
InferenceEngine::IExecutableNetworkInternal::Ptr Engine::LoadExeNetworkImpl(const InferenceEngine::CNNNetwork& network,
const Configs& user_config) {
if (GetCore() == nullptr) {
IE_THROW() << "Please, work with HETERO device via InferencEngine::Core object";
}
if (network.getFunction() == nullptr) {
IE_THROW() << "HETERO device supports only nGraph model representation";
}
return std::make_shared<HeteroExecutableNetwork>(network, user_config, this);
}
InferenceEngine::IExecutableNetworkInternal::Ptr Engine::ImportNetwork(
std::istream& heteroModel,
const std::map<std::string, std::string>& user_config) {
return std::make_shared<HeteroExecutableNetwork>(heteroModel, user_config, this, true);
}
Engine::DeviceMetaInformationMap Engine::GetDevicePlugins(const std::string& targetFallback,
const Configs& device_config) const {
auto fallbackDevices = ov::DeviceIDParser::get_hetero_devices(targetFallback);
Engine::DeviceMetaInformationMap metaDevices;
for (auto&& deviceName : fallbackDevices) {
auto itPlugin = metaDevices.find(deviceName);
if (metaDevices.end() == itPlugin) {
metaDevices[deviceName] = GetCore()->GetSupportedConfig(deviceName, device_config);
}
}
return metaDevices;
}
void Engine::SetConfig(const Configs& user_config) {
for (auto&& kvp : user_config) {
const auto& name = kvp.first;
if (ov::util::contains(getHeteroSupportedConfigKeys(), name))
_config[name] = kvp.second;
else if (ov::util::contains(getHeteroDeviceSupportedConfigKeys(), name))
_device_config[name] = kvp.second;
else
IE_THROW() << "Unsupported HETERO config key: " << name;
}
}
QueryNetworkResult Engine::QueryNetwork(const CNNNetwork& network, const Configs& user_config) const {
if (GetCore() == nullptr) {
IE_THROW() << "Please, work with HETERO device via ov::Core object";
}
auto parsed_config = MergeConfigs(user_config);
std::string fallbackDevicesStr = GetTargetFallback(parsed_config.hetero_config);
DeviceMetaInformationMap metaDevices = GetDevicePlugins(fallbackDevicesStr, parsed_config.device_config);
auto function = network.getFunction();
if (function == nullptr) {
IE_THROW() << "HETERO device supports just nGraph model representation";
}
std::map<std::string, QueryNetworkResult> queryResults;
for (auto&& metaDevice : metaDevices) {
const auto& deviceName = metaDevice.first;
const auto& device_config = metaDevice.second;
queryResults[deviceName] = GetCore()->QueryNetwork(network, deviceName, device_config);
}
// WARNING: Here is devices with user set priority
auto fallbackDevices = ov::DeviceIDParser::get_hetero_devices(fallbackDevicesStr);
QueryNetworkResult qr;
for (auto&& deviceName : fallbackDevices) {
for (auto&& layerQueryResult : queryResults[deviceName].supportedLayersMap) {
qr.supportedLayersMap.emplace(layerQueryResult);
}
}
// set OK status
qr.rc = StatusCode::OK;
return qr;
}
Parameter Engine::GetMetric(const std::string& name, const ov::AnyMap& user_options) const {
if (ov::supported_properties == name) {
return decltype(ov::supported_properties)::value_type{
ov::PropertyName{ov::supported_properties.name(), ov::PropertyMutability::RO},
ov::PropertyName{ov::caching_properties.name(), ov::PropertyMutability::RO},
ov::PropertyName{ov::device::full_name.name(), ov::PropertyMutability::RO},
ov::PropertyName{ov::device::capabilities.name(), ov::PropertyMutability::RO},
ov::PropertyName{ov::device::priorities.name(), ov::PropertyMutability::RW}};
} else if (ov::caching_properties == name) {
return decltype(ov::caching_properties)::value_type{ov::hetero::caching_device_properties.name()};
} else if (ov::hetero::caching_device_properties == name) {
std::string targetFallback = GetTargetFallback(user_options);
return decltype(ov::hetero::caching_device_properties)::value_type{DeviceCachingProperties(targetFallback)};
} else if (METRIC_KEY(SUPPORTED_METRICS) == name) {
IE_SET_METRIC_RETURN(SUPPORTED_METRICS,
std::vector<std::string>{METRIC_KEY(SUPPORTED_METRICS),
ov::device::full_name.name(),
METRIC_KEY(SUPPORTED_CONFIG_KEYS),
METRIC_KEY(IMPORT_EXPORT_SUPPORT),
ov::caching_properties.name(),
ov::device::capabilities.name()});
} else if (METRIC_KEY(SUPPORTED_CONFIG_KEYS) == name) {
IE_SET_METRIC_RETURN(SUPPORTED_CONFIG_KEYS, getSupportedConfigKeys());
} else if (ov::device::full_name == name) {
return decltype(ov::device::full_name)::value_type{"HETERO"};
} else if (METRIC_KEY(IMPORT_EXPORT_SUPPORT) == name) {
IE_SET_METRIC_RETURN(IMPORT_EXPORT_SUPPORT, true);
} else if (ov::device::capabilities == name) {
return decltype(ov::device::capabilities)::value_type{{ov::device::capability::EXPORT_IMPORT}};
} else {
IE_THROW() << "Unsupported HETERO metric key: " << name;
}
}
std::string Engine::DeviceCachingProperties(const std::string& targetFallback) const {
auto fallbackDevices = ov::DeviceIDParser::get_hetero_devices(targetFallback);
// Vector of caching configs for devices
std::vector<ov::AnyMap> result = {};
for (const auto& device : fallbackDevices) {
ov::DeviceIDParser parser(device);
ov::AnyMap properties = {};
// Use name without id
auto device_name = parser.get_device_name();
auto supported_properties =
GetCore()->GetMetric(device, ov::supported_properties.name()).as<std::vector<ov::PropertyName>>();
if (ov::util::contains(supported_properties, ov::caching_properties.name())) {
auto caching_properties =
GetCore()->GetMetric(device, ov::caching_properties.name()).as<std::vector<ov::PropertyName>>();
for (auto& property_name : caching_properties) {
properties[property_name] = GetCore()->GetMetric(device, property_name);
}
// If caching properties are not supported by device, try to add at least device architecture
} else if (ov::util::contains(supported_properties, ov::device::architecture.name())) {
auto device_architecture = GetCore()->GetMetric(device, ov::device::architecture.name());
properties = ov::AnyMap{{ov::device::architecture.name(), device_architecture}};
// Device architecture is not supported, add device name as achitecture
} else {
properties = ov::AnyMap{{ov::device::architecture.name(), device_name}};
}
result.emplace_back(properties);
}
return result.empty() ? "" : ov::Any(result).as<std::string>();
}
Parameter Engine::GetConfig(const std::string& name, const ov::AnyMap& options) const {
if (name == HETERO_CONFIG_KEY(DUMP_GRAPH_DOT)) {
auto it = _config.find(name);
IE_ASSERT(it != _config.end());
bool dump = it->second == YES;
return {dump};
} else if (name == ov::device::priorities) {
std::string targetFallback = GetTargetFallback(options);
auto priorities = ov::util::from_string(targetFallback, ov::device::priorities);
return decltype(ov::device::priorities)::value_type{priorities};
} else if (name == "TARGET_FALLBACK") {
return GetTargetFallback(options);
} else if (name == CONFIG_KEY(EXCLUSIVE_ASYNC_REQUESTS)) {
auto it = _device_config.find(name);
IE_ASSERT(it != _device_config.end());
bool exclusive_async = it->second == YES;
return {exclusive_async};
} else {
IE_THROW() << "Unsupported HETERO config key: " << name;
}
}
static Version heteroPluginDescription = {
{2, 1}, // plugin API version
CI_BUILD_NUMBER,
"heteroPlugin" // plugin description message
};
IE_DEFINE_PLUGIN_CREATE_FUNCTION(Engine, heteroPluginDescription)