rework the config and better follow new api (#15920)

* rework the config to follow new api

Signed-off-by: fishbell <bell.song@intel.com>

* fix tests

Signed-off-by: fishbell <bell.song@intel.com>

* clean up code

Signed-off-by: fishbell <bell.song@intel.com>

* fix missing property

Signed-off-by: fishbell <bell.song@intel.com>

* fix case failure caused by name compliance

Signed-off-by: fishbell <bell.song@intel.com>

* clean up code

Signed-off-by: fishbell <bell.song@intel.com>

* workaround negative values with unsigned type

Signed-off-by: fishbell <bell.song@intel.com>

* fix wrong exception type

Signed-off-by: fishbell <bell.song@intel.com>

* refactor config/metric

Signed-off-by: fishbell <bell.song@intel.com>

* apply review comments

Signed-off-by: fishbell <bell.song@intel.com>

---------

Signed-off-by: fishbell <bell.song@intel.com>
This commit is contained in:
yanlan song authored and GitHub committed 2023-03-03 10:04:28 +08:00
1 parent a16f1923d7
commit 33e0b8caeb
11 files changed
+476 -95

No files matched your search

+3 -3
View File
@@ -322,15 +322,15 @@ void AutoSchedule::TryToLoadNetWork(AutoLoadContext& context, const std::string&
// limit the threads num for compiling
int maxNumThreads = 0;
try {
maxNumThreads = _autoSContext->_core->GetConfig(device, GPU_CONFIG_KEY(MAX_NUM_THREADS)).as<int>();
maxNumThreads = _autoSContext->_core->GetConfig(device, ov::compilation_num_threads.name()).as<int>();
} catch (const IE::Exception&) {
LOG_DEBUG_TAG("cannot get MAX_NUM_THREADS from GPU");
}
if (maxNumThreads == static_cast<int>(std::thread::hardware_concurrency())) {
int threadNum = maxNumThreads / 2;
deviceConfig[GPU_CONFIG_KEY(MAX_NUM_THREADS)] = std::to_string(threadNum).c_str();
deviceConfig[ov::compilation_num_threads.name()] = std::to_string(threadNum).c_str();
LOG_DEBUG_TAG("gpu streams number for compiling: %s",
deviceConfig[GPU_CONFIG_KEY(MAX_NUM_THREADS)].c_str());
deviceConfig[ov::compilation_num_threads.name()].c_str());
} else {
// user set the compiling threads num
// use the user's val anyway
+109 -81
View File
@@ -52,11 +52,52 @@ namespace {
}
return METRIC_VALUE(FP32);
}
int MapPriorityValues(ov::hint::Priority priority) {
switch (priority) {
case ov::hint::Priority::HIGH:
return 0;
case ov::hint::Priority::MEDIUM:
return 1;
case ov::hint::Priority::LOW:
return 2;
default:
return 1;
}
}
std::map<std::string, std::string> ConvertToStringMap(ov::AnyMap& properties) {
std::map<std::string, std::string> configs;
for (auto& property : properties) {
configs[property.first] = property.second.as<std::string>();
}
return configs;
}
} // namespace
std::mutex MultiDeviceInferencePlugin::_mtx;
std::map<unsigned int, std::list<std::string>> MultiDeviceInferencePlugin::_priorityMap;
ov::AnyMap MultiDeviceInferencePlugin::PreProcessConfig(const std::map<std::string, std::string>& orig_config) const {
ov::AnyMap properties = ov::AnyMap(orig_config.begin(), orig_config.end());
for (auto& property : properties) {
// for model_priority, the values need to be converted
if (property.first == ov::hint::model_priority.name()) {
ov::Any converted_val{nullptr};
auto legacy_val = property.second.as<std::string>();
if (legacy_val == InferenceEngine::PluginConfigParams::MODEL_PRIORITY_HIGH) {
converted_val = ov::hint::Priority::HIGH;
} else if (legacy_val == InferenceEngine::PluginConfigParams::MODEL_PRIORITY_MED) {
converted_val = ov::hint::Priority::MEDIUM;
} else if (legacy_val == InferenceEngine::PluginConfigParams::MODEL_PRIORITY_LOW) {
converted_val = ov::hint::Priority::LOW;
} else {
converted_val = legacy_val;
}
property.second = converted_val;
}
}
return properties;
}
std::vector<DeviceInformation> MultiDeviceInferencePlugin::ParseMetaDevices(const std::string& priorities,
const std::map<std::string, std::string> & config) const {
std::vector<DeviceInformation> metaDevices;
@@ -220,48 +261,31 @@ std::vector<DeviceInformation> MultiDeviceInferencePlugin::ParseMetaDevices(cons
InferenceEngine::Parameter MultiDeviceInferencePlugin::GetConfig(const std::string& name,
const std::map<std::string, InferenceEngine::Parameter> & options) const {
Parameter result;
const bool is_new_api = IsNewAPI();
if (_pluginConfig._keyConfigMap.find(name) != _pluginConfig._keyConfigMap.end()) {
std::string val = _pluginConfig._keyConfigMap.find(name)->second;
if (is_new_api) {
if (name == ov::enable_profiling) {
return val == PluginConfigParams::YES ? true : false;
} else if (name == ov::hint::model_priority) {
return ov::util::from_string(val, ov::hint::model_priority);
} else if (name == ov::hint::performance_mode) {
return ov::util::from_string(val, ov::hint::performance_mode);
} else if (name == ov::hint::num_requests) {
auto temp = ov::util::from_string(val, ov::hint::num_requests);
return temp;
} else if (name == ov::device::id) {
return ov::util::from_string(val, ov::device::id);
} else if (name == ov::hint::allow_auto_batching) {
return val == PluginConfigParams::YES ? true : false;
} else if (name == ov::auto_batch_timeout) {
return ov::util::from_string(val, ov::auto_batch_timeout);
} else if (name == ov::intel_auto::device_bind_buffer) {
return val == PluginConfigParams::YES ? true : false;
} else if (name == ov::log::level) {
return ov::util::from_string(val, ov::log::level);
} else if (name == ov::device::priorities) {
return ov::util::from_string(val, ov::device::priorities);
} else if (name == ov::intel_auto::enable_startup_fallback) {
return val == PluginConfigParams::YES ? true : false;
} else {
return val;
auto val = _pluginConfig.get_property(name);
if (!IsNewAPI()) {
if (name == ov::hint::model_priority.name()) { // need to convert priority values to old API
ov::Any legacy_val{nullptr};
if (!val.empty()) {
switch (val.as<ov::hint::Priority>()) {
case ov::hint::Priority::LOW: legacy_val = InferenceEngine::PluginConfigParams::MODEL_PRIORITY_LOW; break;
case ov::hint::Priority::MEDIUM: legacy_val = InferenceEngine::PluginConfigParams::MODEL_PRIORITY_MED; break;
case ov::hint::Priority::HIGH: legacy_val = InferenceEngine::PluginConfigParams::MODEL_PRIORITY_HIGH; break;
default: OPENVINO_ASSERT(false, "Unsupported model priority value");
}
}
return legacy_val;
} else {
return val;
}
} else {
IE_THROW() << "Unsupported config key : " << name;
return val;
}
return result;
return val;
}
void MultiDeviceInferencePlugin::SetConfig(const std::map<std::string, std::string> & config) {
_pluginConfig.UpdateFromMap(config, GetName());
// with setConfig, only multi/auto supported internal configs can be accepted
_pluginConfig.set_property(PreProcessConfig(config));
}
static const Version version = {{2, 1}, CI_BUILD_NUMBER, "MultiDevicePlugin"};
@@ -331,31 +355,36 @@ IExecutableNetworkInternal::Ptr MultiDeviceInferencePlugin::LoadNetworkImpl(cons
}
// to use plugin's name as the log tag
_LogTag = GetName();
auto loadConfig = _pluginConfig;
// updateFromMap will check config valid
loadConfig.UpdateFromMap(config, GetName(), true);
auto fullConfig = loadConfig._keyConfigMap;
bool workModeAuto = GetName() == "AUTO";
// Remove the performance hint if no setting to this property from user.
if (!loadConfig._isSetPerHint) {
fullConfig.erase(PluginConfigParams::KEY_PERFORMANCE_HINT);
auto loadConfig = _pluginConfig;
// if no perf hint from user with compiled model, or already been set with plugin
// apply latency for AUTO, tput for MULTI
bool isHintSet = _pluginConfig.is_set_by_user(ov::hint::performance_mode) || config.find(ov::hint::performance_mode.name()) != config.end();
if (!isHintSet) {
if (workModeAuto) {
// set performance hint to 'LATENCY' model for AutoExecutable Network.
loadConfig._perfHintsConfig.SetConfig(PluginConfigParams::KEY_PERFORMANCE_HINT,
PluginConfigParams::LATENCY);
loadConfig.set_property(ov::hint::performance_mode(ov::hint::PerformanceMode::LATENCY));
} else {
// set performance hint to 'THROUGHPUT' model for MultiExecutable Network.
loadConfig._perfHintsConfig.SetConfig(PluginConfigParams::KEY_PERFORMANCE_HINT,
PluginConfigParams::THROUGHPUT);
loadConfig.set_property(ov::hint::performance_mode(ov::hint::PerformanceMode::THROUGHPUT));
}
}
if (!loadConfig._isSetCacheDir)
fullConfig.erase(CONFIG_KEY(CACHE_DIR));
// updateFromMap will check config valid
loadConfig.set_user_property(PreProcessConfig(config), workModeAuto? true : false);
loadConfig.apply_user_properties();
auto fullProperty = loadConfig.get_full_properties();
// this can be updated when plugin switch to 2.0 API
std::map<std::string, std::string> fullConfig = ConvertToStringMap(fullProperty);
// Remove the performance hint as this is set by plugin logic, not from user
if (!isHintSet)
fullConfig.erase(ov::hint::performance_mode.name());
if (!loadConfig.is_set_by_user(ov::cache_dir))
fullConfig.erase(ov::cache_dir.name());
// collect the settings that are applicable to the devices we are loading the network to
std::unordered_map<std::string, InferenceEngine::Parameter> multiNetworkConfig;
std::unordered_map<std::string, ov::Any> multiNetworkConfig;
std::vector<DeviceInformation> metaDevices;
auto priorities = fullConfig.find(MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES);
if (priorities->second.find("AUTO") != std::string::npos || priorities->second.find("MULTI") != std::string::npos) {
auto priorities = loadConfig.get_property(ov::device::priorities);
if (priorities.find("AUTO") != std::string::npos || priorities.find("MULTI") != std::string::npos) {
IE_THROW() << "The device candidate list should not include the meta plugin for " << GetName() << " device";
}
// If the user sets the property, insert the property into the deviceConfig
@@ -385,13 +414,13 @@ IExecutableNetworkInternal::Ptr MultiDeviceInferencePlugin::LoadNetworkImpl(cons
std::map<std::string, std::string> filterConfig;
auto strDevices = GetDeviceList(fullConfig);
// fill in the context for auto
if (loadConfig._useProfiling) {
filterConfig.insert({PluginConfigParams::KEY_PERF_COUNT, PluginConfigParams::YES});
if (loadConfig.get_property(ov::enable_profiling)) {
filterConfig.insert({ov::enable_profiling.name(), PluginConfigParams::YES});
autoSContext->_needPerfCounters = true;
}
autoSContext->_modelPriority = loadConfig._modelPriority;
autoSContext->_batchingDisabled = loadConfig._disableAutoBatching;
autoSContext->_performanceHint = loadConfig._perfHintsConfig.GetConfig(PluginConfigParams::KEY_PERFORMANCE_HINT).as<std::string>();
autoSContext->_modelPriority = MapPriorityValues(loadConfig.get_property(ov::hint::model_priority));
autoSContext->_batchingDisabled = !(loadConfig.get_property(ov::hint::allow_auto_batching));
autoSContext->_performanceHint = loadConfig.get_property(ov::hint::performance_mode.name()).as<std::string>();
// filter the device that supports filter configure
auto metaDevices = ParseMetaDevices(strDevices, fullConfig);
auto supportDevicesByConfig = FilterDevice(metaDevices, filterConfig);
@@ -436,11 +465,11 @@ IExecutableNetworkInternal::Ptr MultiDeviceInferencePlugin::LoadNetworkImpl(cons
config.second.c_str());
}
// carry on batch configs only if user explicitly sets
if (config.find(CONFIG_KEY(ALLOW_AUTO_BATCHING)) != config.end() || loadConfig._isBatchConfigSet)
insertPropToConfig(CONFIG_KEY(ALLOW_AUTO_BATCHING), iter->deviceName, configs);
if (config.find(CONFIG_KEY(AUTO_BATCH_TIMEOUT)) != config.end())
insertPropToConfig(CONFIG_KEY(AUTO_BATCH_TIMEOUT), iter->deviceName, configs);
insertPropToConfig(CONFIG_KEY(CACHE_DIR), iter->deviceName, configs);
if (loadConfig.is_set_by_user(ov::hint::allow_auto_batching))
insertPropToConfig(ov::hint::allow_auto_batching.name(), iter->deviceName, configs);
if (loadConfig.is_set_by_user(ov::auto_batch_timeout))
insertPropToConfig(ov::auto_batch_timeout.name(), iter->deviceName, configs);
insertPropToConfig(ov::cache_dir.name(), iter->deviceName, configs);
LOG_INFO_TAG("device:%s, priority:%ld", iter->deviceName.c_str(), iter->devicePriority);
}
autoSContext->_modelPath = clonedModelPath;
@@ -452,12 +481,8 @@ IExecutableNetworkInternal::Ptr MultiDeviceInferencePlugin::LoadNetworkImpl(cons
autoSContext->_plugin = this;
autoSContext->_core = GetCore();
autoSContext->_LogTag = _LogTag;
auto tmpiter = fullConfig.find(ov::intel_auto::device_bind_buffer.name());
if (tmpiter != fullConfig.end() && tmpiter->second == PluginConfigParams::YES)
autoSContext->_bindBuffer = true;
auto tmpiter_enableStartupFallback = fullConfig.find(ov::intel_auto::enable_startup_fallback.name());
if (tmpiter_enableStartupFallback != fullConfig.end() && tmpiter_enableStartupFallback->second == PluginConfigParams::NO)
autoSContext->_startupfallback = false;
autoSContext->_bindBuffer = loadConfig.get_property(ov::intel_auto::device_bind_buffer);
autoSContext->_startupfallback = loadConfig.get_property(ov::intel_auto::enable_startup_fallback);
return std::make_shared<AutoExecutableNetwork>(autoSContext, std::make_shared<AutoSchedule>());
}
OV_ITT_SCOPED_TASK(itt::domains::MULTIPlugin, "MultiDeviceInferencePlugin::LoadNetworkImpl:MultiMode");
@@ -471,18 +496,18 @@ IExecutableNetworkInternal::Ptr MultiDeviceInferencePlugin::LoadNetworkImpl(cons
_LogTag = "AUTO";
LOG_INFO_TAG("CUMULATIVE Call MULTI PERFORMANCE_HINT set to THROUGHPUT");
}
if (priorities->second.empty()) {
if (priorities.empty()) {
IE_THROW() << "KEY_MULTI_DEVICE_PRIORITIES key is not set for " << GetName() << " device";
} else { // for use case -d MULTI:xPU or -d AUTO:xPU
auto metaDevicesByConfig = ParseMetaDevices(priorities->second, fullConfig);
auto metaDevicesByConfig = ParseMetaDevices(priorities, fullConfig);
metaDevices = modelPath.empty() ? FilterDeviceByNetwork(metaDevicesByConfig, network)
: metaDevicesByConfig;
if (metaDevicesByConfig.size() != metaDevices.size()) {
LOG_DEBUG_TAG("stateful/dynamic model, loaded to single device");
multiNetworkConfig[MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES]
multiNetworkConfig[ov::device::priorities.name()]
= metaDevices[0].deviceName;
} else {
multiNetworkConfig.insert(*priorities);
multiNetworkConfig[ov::device::priorities.name()] = priorities;
}
}
auto multiSContext = std::make_shared<MultiScheduleContext>();
@@ -498,12 +523,12 @@ IExecutableNetworkInternal::Ptr MultiDeviceInferencePlugin::LoadNetworkImpl(cons
LOG_INFO_TAG("set %s=%s", tmpiter->first.c_str(), tmpiter->second.c_str());
multiSContext->_batchingDisabled = true;
}
if (config.find(CONFIG_KEY(ALLOW_AUTO_BATCHING)) != config.end() || loadConfig._isBatchConfigSet)
if (loadConfig.is_set_by_user(ov::hint::allow_auto_batching))
p.config.insert({tmpiter->first, tmpiter->second});
}
if (config.find(CONFIG_KEY(AUTO_BATCH_TIMEOUT)) != config.end())
insertPropToConfig(CONFIG_KEY(AUTO_BATCH_TIMEOUT), p.deviceName, p.config);
insertPropToConfig(CONFIG_KEY(CACHE_DIR), p.deviceName, p.config);
if (loadConfig.is_set_by_user(ov::auto_batch_timeout))
insertPropToConfig(ov::auto_batch_timeout.name(), p.deviceName, p.config);
insertPropToConfig(ov::cache_dir.name(), p.deviceName, p.config);
const auto& deviceName = p.deviceName;
const auto& deviceConfig = p.config;
SoExecutableNetworkInternal exec_net;
@@ -526,8 +551,8 @@ IExecutableNetworkInternal::Ptr MultiDeviceInferencePlugin::LoadNetworkImpl(cons
sStreamNums = exec_net->GetMetric(ov::num_streams.name()).as<std::string>();
sThreadNums = exec_net->GetMetric(ov::inference_num_threads.name()).as<std::string>();
} else if (deviceName.find("GPU") != std::string::npos) {
sStreamNums = exec_net->GetConfig(PluginConfigParams::KEY_GPU_THROUGHPUT_STREAMS).as<std::string>();
sThreadNums = exec_net->GetConfig(GPUConfigParams::KEY_GPU_MAX_NUM_THREADS).as<std::string>();
sStreamNums = exec_net->GetConfig(ov::num_streams.name()).as<std::string>();
sThreadNums = exec_net->GetConfig(ov::compilation_num_threads.name()).as<std::string>();
}
// print CPU or GPU streams num and threads num
@@ -610,8 +635,8 @@ IExecutableNetworkInternal::Ptr MultiDeviceInferencePlugin::LoadNetworkImpl(cons
multiSContext->_core = GetCore();
multiSContext->_LogTag = _LogTag;
IExecutableNetworkInternal::Ptr impl;
auto tmpiter = fullConfig.find(ov::intel_auto::device_bind_buffer.name());
if (tmpiter != fullConfig.end() && tmpiter->second == PluginConfigParams::YES) {
auto tmp = loadConfig.get_property(ov::intel_auto::device_bind_buffer);
if (tmp) {
multiSContext->_bindBuffer = true;
impl = std::make_shared<MultiExecutableNetwork>(multiSContext, std::make_shared<BinderMultiSchedule>());
} else {
@@ -644,9 +669,12 @@ QueryNetworkResult MultiDeviceInferencePlugin::QueryNetwork(const CNNNetwork&
auto queryconfig = _pluginConfig;
// updateFromMap will check config valid
queryconfig.UpdateFromMap(config, GetName(), true);
auto fullConfig = queryconfig._keyConfigMap;
auto priorities = fullConfig.find(MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES);
queryconfig.set_user_property(PreProcessConfig(config), (GetName() == "AUTO")? true : false);
queryconfig.apply_user_properties();
auto fullproperty = queryconfig.get_full_properties();
// this can be updated when plugin switch to 2.0 API
std::map<std::string, std::string> fullConfig = ConvertToStringMap(fullproperty);;
auto priorities = fullConfig.find(ov::device::priorities.name());
if (!priorities->second.empty()) {
auto metaDevices = ParseMetaDevices(priorities->second, fullConfig);
std::unordered_set<std::string> supportedLayers;
@@ -820,7 +848,7 @@ void MultiDeviceInferencePlugin::RegisterPriority(const unsigned int& priority,
std::string MultiDeviceInferencePlugin::GetDeviceList(const std::map<std::string, std::string>& config) const {
std::string allDevices;
auto deviceList = GetCore()->GetAvailableDevices();
auto deviceListConfig = config.find(MultiDeviceConfigParams::KEY_MULTI_DEVICE_PRIORITIES);
auto deviceListConfig = config.find(ov::device::priorities.name());
if (deviceListConfig->second.empty()) {
for (auto&& device : deviceList) {
// filter out the supported devices
+4 -2
View File
@@ -14,7 +14,7 @@
#include <cpp_interfaces/interface/ie_internal_plugin_config.hpp>
#include "utils/log_util.hpp"
#include "common.hpp"
#include "utils/config.hpp"
#include "utils/plugin_config.hpp"
#ifdef MULTIUNITTEST
#define MOCKTESTMACRO virtual
@@ -61,12 +61,13 @@ protected:
std::map<std::string, std::string> GetSupportedConfig(const std::map<std::string, std::string>& config,
const MultiDevicePlugin::DeviceName & deviceName) const;
ov::AnyMap PreProcessConfig(const std::map<std::string, std::string>& orig_config) const;
private:
InferenceEngine::IExecutableNetworkInternal::Ptr LoadNetworkImpl(const std::string& modelPath,
InferenceEngine::CNNNetwork network,
const std::map<std::string, std::string>& config,
const std::string &networkPrecision = METRIC_VALUE(FP32));
PluginConfig _pluginConfig;
std::vector<DeviceInformation> FilterDevice(const std::vector<DeviceInformation>& metaDevices,
const std::map<std::string, std::string>& config);
std::vector<DeviceInformation> FilterDeviceByNetwork(const std::vector<DeviceInformation>& metaDevices,
@@ -75,6 +76,7 @@ private:
static std::mutex _mtx;
static std::map<unsigned int, std::list<std::string>> _priorityMap;
std::string _LogTag;
PluginConfig _pluginConfig;
};
} // namespace MultiDevicePlugin
+115
View File
@@ -0,0 +1,115 @@
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "utils/plugin_config.hpp"
namespace MultiDevicePlugin {
const std::set<std::string> PluginConfig::_availableDevices = {"AUTO", "CPU", "GPU", "TEMPLATE", "NVIDIA", "VPUX", "MULTI", "HETERO", "mock"};
PluginConfig::PluginConfig() {
set_default();
device_property_validator = std::dynamic_pointer_cast<BaseValidator>(std::make_shared<FuncValidator>([](const ov::Any& target) -> bool {
auto deviceName = target.as<std::string>();
return _availableDevices.end() != std::find(_availableDevices.begin(), _availableDevices.end(),
DeviceIDParser(deviceName).getDeviceName());
}));
}
void PluginConfig::set_default() {
register_property(
std::make_tuple(ov::enable_profiling, false),
std::make_tuple(ov::device::priorities, ""),
std::make_tuple(ov::hint::model_priority, ov::hint::Priority::MEDIUM),
std::make_tuple(ov::log::level, ov::log::Level::NO),
std::make_tuple(ov::intel_auto::device_bind_buffer, false),
std::make_tuple(ov::hint::performance_mode, ov::hint::PerformanceMode::UNDEFINED),
std::make_tuple(ov::hint::num_requests, 0, UnsignedTypeValidator()),
std::make_tuple(ov::intel_auto::enable_startup_fallback, true),
// TODO 1) cache_dir 2) allow_auto_batch 3) auto_batch_timeout
std::make_tuple(ov::cache_dir, ""),
std::make_tuple(ov::hint::allow_auto_batching, true),
std::make_tuple(ov::auto_batch_timeout, 1000),
// Legacy API properties
std::make_tuple(exclusive_asyc_requests, false),
// RO for register only
std::make_tuple(ov::device::full_name),
std::make_tuple(ov::device::capabilities),
std::make_tuple(ov::supported_properties));
}
void PluginConfig::register_property_impl(const ov::AnyMap::value_type& property, ov::PropertyMutability mutability, BaseValidator::Ptr validator) {
property_validators[property.first] = validator;
internal_properties[property.first] = property.second;
property_mutabilities[property.first] = mutability;
}
template <typename T, ov::PropertyMutability mutability>
void PluginConfig::register_property_impl(const ov::Property<T, mutability>& property) {
property_mutabilities[property.name()] = mutability;
}
void PluginConfig::set_property(const ov::AnyMap& properties) {
for (auto& kv : properties) {
auto& name = kv.first;
auto& val = kv.second;
if (is_supported(kv.first)) {
OPENVINO_ASSERT(property_validators.at(name)->is_valid(val),
"Invalid value for property ", name, ": ", val.as<std::string>());
internal_properties[name] = val;
// when user call set_property to set some config to plugin, we also respect this and pass through the config in this case
user_properties[name] = val;
} else {
OPENVINO_ASSERT(false, "property:", name, ": not supported");
}
}
}
ov::Any PluginConfig::get_property(const std::string& name) const {
OPENVINO_ASSERT(internal_properties.find(name) != internal_properties.end(), "[AUTO]", "not supported property ", name);
return internal_properties.at(name);
}
bool PluginConfig::is_supported(const std::string& name) const {
bool supported = internal_properties.find(name) != internal_properties.end();
bool has_validator = property_validators.find(name) != property_validators.end();
return supported && has_validator;
}
bool PluginConfig::is_set_by_user(const std::string& name) const {
return user_properties.find(name) != user_properties.end();
}
void PluginConfig::set_user_property(const ov::AnyMap& config, bool checkfirstlevel) {
// user property, accept either internal property, or secondary property for hardware plugin
// TODO: for multi, other first level property are also accepted
for (auto& kv : config) {
auto& name = kv.first;
auto& val = kv.second;
if (is_supported(name)) {
OPENVINO_ASSERT(property_validators.at(name)->is_valid(val),
"Invalid value for property ", name, ": ", val.as<std::string>());
internal_properties[kv.first] = kv.second;
user_properties[kv.first] = kv.second;
} else {
if (device_property_validator->is_valid(ov::Any(name))) { // if it's a valid secondary, accept it
user_properties[kv.first] = kv.second;
} else if (!checkfirstlevel) { // for multi, accept it anyway when compiled model
user_properties[kv.first] = kv.second;
} else {
OPENVINO_ASSERT(false, "property", name, ": not supported");
}
}
}
}
void PluginConfig::apply_user_properties() {
full_properties = internal_properties;
for (auto& kv : user_properties)
full_properties[kv.first] = kv.second;
}
ov::AnyMap PluginConfig::get_full_properties() {
return full_properties;
}
} // namespace MultiDevicePlugin
+236
View File
@@ -0,0 +1,236 @@
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "ie_parameter.hpp"
#include "ie_performance_hints.hpp"
#include "ie_icore.hpp"
#include "openvino/runtime/auto/properties.hpp"
#include "log.hpp"
#include <string>
#include <map>
#include <vector>
namespace MultiDevicePlugin {
using namespace InferenceEngine;
// legacy config
static constexpr ov::Property<bool, ov::PropertyMutability::RW> exclusive_asyc_requests{"EXCLUSIVE_ASYNC_REQUESTS"};
class BaseValidator {
public:
using Ptr = std::shared_ptr<BaseValidator>;
virtual ~BaseValidator() = default;
virtual bool is_valid(const ov::Any& v) const = 0;
};
class FuncValidator : public BaseValidator {
public:
explicit FuncValidator(std::function<bool(const ov::Any&)> func) : m_func(func) { }
bool is_valid(const ov::Any& v) const override {
return m_func(v);
}
private:
std::function<bool(const ov::Any&)> m_func;
};
template<typename T>
class PropertyTypeValidator : public BaseValidator {
public:
bool is_valid(const ov::Any& v) const override {
try {
v.as<T>();
return true;
} catch (ov::Exception&) {
return false;
}
}
};
class UnsignedTypeValidator : public BaseValidator {
public:
bool is_valid(const ov::Any& v) const override {
int val_i = -1;
try {
// work around for negative value check (inconsistent behavior on windows/linux)
auto val = v.as<std::string>();
val_i = std::stoi(val);
if (val_i >= 0)
return true;
else
throw std::logic_error("wrong val");
} catch (std::exception&) {
return false;
}
}
};
class PluginConfig {
public:
PluginConfig();
PluginConfig(std::initializer_list<ov::AnyMap::value_type> values) { set_property(ov::AnyMap(values)); }
void set_default();
void set_property(const ov::AnyMap& properties);
void set_user_property(const ov::AnyMap& properties, bool checkfirstlevel = true);
ov::Any get_property(const std::string& name) const;
bool is_set_by_user(const std::string& name) const;
bool is_supported(const std::string& name) const;
void register_property_impl(const ov::AnyMap::value_type& property, ov::PropertyMutability mutability, BaseValidator::Ptr validator = nullptr);
template <typename T, ov::PropertyMutability mutability>
void register_property_impl(const ov::Property<T, mutability>&);
template <typename... PropertyInitializer, typename std::enable_if<(sizeof...(PropertyInitializer) == 0), bool>::type = true>
void register_property_impl() { }
template <typename ValueT, typename... PropertyInitializer>
void register_property_impl(const std::tuple<ov::device::Priorities, ValueT>& property, PropertyInitializer&&... properties) {
auto p = std::get<0>(property)(std::get<1>(property));
auto v = std::dynamic_pointer_cast<BaseValidator>(std::make_shared<PropertyTypeValidator<std::string>>());
register_property_impl(std::move(p), ov::PropertyMutability::RW, std::move(v));
register_property_impl(properties...);
}
template <typename T, ov::PropertyMutability mutability, typename... PropertyInitializer>
void register_property_impl(const std::tuple<ov::Property<T, mutability>>& property, PropertyInitializer&&... properties) {
auto p = std::get<0>(property);
register_property_impl(std::move(p));
register_property_impl(properties...);
}
template <typename T, ov::PropertyMutability mutability, typename ValueT, typename... PropertyInitializer>
void register_property_impl(const std::tuple<ov::Property<T, mutability>, ValueT>& property, PropertyInitializer&&... properties) {
auto p = std::get<0>(property)(std::get<1>(property));
auto v = std::dynamic_pointer_cast<BaseValidator>(std::make_shared<PropertyTypeValidator<T>>());
register_property_impl(std::move(p), mutability, std::move(v));
register_property_impl(properties...);
}
template <typename T,
ov::PropertyMutability mutability,
typename ValueT,
typename ValidatorT,
typename... PropertyInitializer>
typename std::enable_if<std::is_base_of<BaseValidator, ValidatorT>::value, void>::type
register_property_impl(const std::tuple<ov::Property<T, mutability>, ValueT, ValidatorT>& property, PropertyInitializer&&... properties) {
auto p = std::get<0>(property)(std::get<1>(property));
auto v = std::dynamic_pointer_cast<BaseValidator>(std::make_shared<ValidatorT>(std::get<2>(property)));
register_property_impl(std::move(p), mutability, std::move(v));
register_property_impl(properties...);
}
template <typename... PropertyInitializer>
void register_property(PropertyInitializer&&... properties) {
register_property_impl(properties...);
}
template <typename... Properties>
ov::util::EnableIfAllStringAny<void, Properties...> set_property(Properties&&... properties) {
set_property(ov::AnyMap{std::forward<Properties>(properties)...});
}
template <typename... Properties>
ov::util::EnableIfAllStringAny<void, Properties...> set_user_property(Properties&&... properties) {
set_user_property(ov::AnyMap{std::forward<Properties>(properties)...});
}
template <typename T, ov::PropertyMutability mutability>
bool is_set_by_user(const ov::Property<T, mutability>& property) const {
return is_set_by_user(property.name());
}
template <typename T, ov::PropertyMutability mutability>
T get_property(const ov::Property<T, mutability>& property) const {
return get_property(property.name()).template as<T>();
}
void apply_user_properties();
ov::AnyMap get_full_properties();
std::vector<std::string> supportedConfigKeys(const std::string& pluginName = "AUTO") const {
std::vector<std::string> supported_configKeys;
for (const auto& iter : property_mutabilities) {
if (iter.second.as<ov::PropertyMutability>() == ov::PropertyMutability::RW)
supported_configKeys.push_back(iter.first);
}
auto multi_supported_configKeys = supported_configKeys;
multi_supported_configKeys.erase(std::remove(
multi_supported_configKeys.begin(), multi_supported_configKeys.end(), ov::intel_auto::enable_startup_fallback.name()),
multi_supported_configKeys.end());
return pluginName == "AUTO" ? supported_configKeys : multi_supported_configKeys;
}
std::vector<ov::PropertyName> supportedProperties(const std::string& pluginName = "AUTO") const {
std::vector<ov::PropertyName> supported_properties;
for (const auto& iter : property_mutabilities)
supported_properties.push_back(ov::PropertyName(iter.first, iter.second.as<ov::PropertyMutability>()));
auto multi_supported_properties = supported_properties;
multi_supported_properties.erase(std::remove(
multi_supported_properties.begin(), multi_supported_properties.end(), ov::intel_auto::enable_startup_fallback),
multi_supported_properties.end());
return pluginName == "AUTO" ? supported_properties : multi_supported_properties;
}
std::vector<std::string> supportedMetrics(const std::string& pluginName = "AUTO") const {
std::vector<std::string> supported_metrics;
for (const auto& iter : property_mutabilities) {
if (iter.second.as<ov::PropertyMutability>() == ov::PropertyMutability::RO)
supported_metrics.push_back(iter.first);
}
supported_metrics.push_back(METRIC_KEY(SUPPORTED_METRICS));
supported_metrics.push_back(METRIC_KEY(SUPPORTED_CONFIG_KEYS));
auto multi_supported_metrics = supported_metrics;
return pluginName == "AUTO" ? supported_metrics : multi_supported_metrics;
}
bool isSupportedDevice(const std::string& deviceName) const {
if (deviceName.empty())
return false;
auto realDevName = deviceName[0] != '-' ? deviceName : deviceName.substr(1);
if (realDevName.empty()) {
return false;
}
realDevName = DeviceIDParser(realDevName).getDeviceName();
std::string::size_type realEndPos = 0;
if ((realEndPos = realDevName.find('(')) != std::string::npos) {
realDevName = realDevName.substr(0, realEndPos);
}
if (_availableDevices.end() == std::find(_availableDevices.begin(), _availableDevices.end(), realDevName)) {
return false;
}
return true;
}
std::vector<std::string> ParsePrioritiesDevices(const std::string& priorities, const char separator = ',') const {
std::vector<std::string> devices;
std::string::size_type pos = 0;
std::string::size_type endpos = 0;
while ((endpos = priorities.find(separator, pos)) != std::string::npos) {
auto subStr = priorities.substr(pos, endpos - pos);
if (!isSupportedDevice(subStr)) {
IE_THROW() << "Unavailable device name: " << subStr;
}
devices.push_back(subStr);
pos = endpos + 1;
}
auto subStr = priorities.substr(pos, priorities.length() - pos);
if (!isSupportedDevice(subStr)) {
IE_THROW() << "Unavailable device name: " << subStr;
}
devices.push_back(subStr);
return devices;
}
private:
ov::AnyMap internal_properties; // internal supported properties for auto/multi
ov::AnyMap user_properties; // user set properties, including secondary properties
ov::AnyMap full_properties; // combined with user set properties, including secondary properties
ov::AnyMap property_mutabilities; // mutability for supported configs/metrics installation
std::map<std::string, BaseValidator::Ptr> property_validators;
BaseValidator::Ptr device_property_validator;
static const std::set<std::string> _availableDevices;
};
} // namespace MultiDevicePlugin
@@ -295,7 +295,7 @@ public:
std::vector<std::string> configKeys = {"SUPPORTED_CONFIG_KEYS", "NUM_STREAMS"};
ON_CALL(*core, GetMetric(_, StrEq(METRIC_KEY(SUPPORTED_CONFIG_KEYS)), _)).WillByDefault(Return(configKeys));
ON_CALL(*core, GetConfig(_, StrEq(GPU_CONFIG_KEY(MAX_NUM_THREADS)))).WillByDefault(Return(12));
ON_CALL(*core, GetConfig(_, StrEq(ov::compilation_num_threads.name()))).WillByDefault(Return(12));
ON_CALL(*plugin, ParseMetaDevices)
.WillByDefault(
@@ -174,7 +174,7 @@ public:
std::vector<std::string> configKeys = {"SUPPORTED_CONFIG_KEYS", "NUM_STREAMS"};
ON_CALL(*core, GetMetric(_, StrEq(METRIC_KEY(SUPPORTED_CONFIG_KEYS)), _)).WillByDefault(Return(configKeys));
ON_CALL(*core, GetConfig(_, StrEq(GPU_CONFIG_KEY(MAX_NUM_THREADS)))).WillByDefault(Return(12));
ON_CALL(*core, GetConfig(_, StrEq(ov::compilation_num_threads.name()))).WillByDefault(Return(12));
ON_CALL(*plugin, ParseMetaDevices)
.WillByDefault(
@@ -118,7 +118,7 @@ public:
IE_SET_METRIC(SUPPORTED_CONFIG_KEYS, supportConfigs, {});
ON_CALL(*core, GetMetric(_, StrEq(METRIC_KEY(SUPPORTED_CONFIG_KEYS)), _))
.WillByDefault(Return(supportConfigs));
ON_CALL(*core, GetConfig(_, StrEq(GPU_CONFIG_KEY(MAX_NUM_THREADS))))
ON_CALL(*core, GetConfig(_, StrEq(ov::compilation_num_threads.name())))
.WillByDefault(Return(12));
}
};
@@ -161,7 +161,7 @@ public:
ON_CALL(*core, GetMetric(_, StrEq(METRIC_KEY(SUPPORTED_CONFIG_KEYS)), _))
.WillByDefault(Return(supportConfigs));
EXPECT_CALL(*core, GetMetric(_, StrEq(METRIC_KEY(SUPPORTED_CONFIG_KEYS)), _)).Times(AnyNumber());
ON_CALL(*core, GetConfig(_, StrEq(GPU_CONFIG_KEY(MAX_NUM_THREADS))))
ON_CALL(*core, GetConfig(_, StrEq(ov::compilation_num_threads.name())))
.WillByDefault(Return(12));
}
};
@@ -92,7 +92,7 @@ public:
IE_SET_METRIC(SUPPORTED_CONFIG_KEYS, supportConfigs, {});
ON_CALL(*core, GetMetric(_, StrEq(METRIC_KEY(SUPPORTED_CONFIG_KEYS)), _))
.WillByDefault(Return(supportConfigs));
ON_CALL(*core, GetConfig(_, StrEq(GPU_CONFIG_KEY(MAX_NUM_THREADS))))
ON_CALL(*core, GetConfig(_, StrEq(ov::compilation_num_threads.name())))
.WillByDefault(Return(12));
}
};
@@ -268,13 +268,13 @@ TEST_P(ExecNetworkGetMetricOptimalNumInferReq, OPTIMAL_NUMBER_OF_INFER_REQUESTS)
ON_CALL(*core.get(), GetConfig(_, StrEq(CONFIG_KEY(PERFORMANCE_HINT_NUM_REQUESTS))))
.WillByDefault(Return(std::to_string(gpuPerfHintNum)));
EXPECT_CALL(*core.get(), GetConfig(_, StrEq(CONFIG_KEY(PERFORMANCE_HINT_NUM_REQUESTS)))).Times(AnyNumber());
ON_CALL(*core, GetConfig(_, StrEq(GPU_CONFIG_KEY(MAX_NUM_THREADS))))
ON_CALL(*core, GetConfig(_, StrEq(ov::compilation_num_threads.name())))
.WillByDefault(Return(8));
EXPECT_CALL(*core.get(), GetConfig(_, StrEq(GPU_CONFIG_KEY(MAX_NUM_THREADS)))).Times(AnyNumber());
EXPECT_CALL(*core.get(), GetConfig(_, StrEq(ov::compilation_num_threads.name()))).Times(AnyNumber());
} else {
metaDevices.push_back({CommonTestUtils::DEVICE_CPU, {}, cpuCustomerNum, ""});
metaDevices.push_back({actualDeviceName, {}, actualCustomerNum, ""});
ON_CALL(*core, GetConfig(_, StrEq(GPU_CONFIG_KEY(MAX_NUM_THREADS)))).WillByDefault(Return(8));
ON_CALL(*core, GetConfig(_, StrEq(ov::compilation_num_threads.name()))).WillByDefault(Return(8));
}
ON_CALL(*plugin, SelectDevice(_, _, _)).WillByDefault(Return(metaDevices[1]));
ON_CALL(*plugin, ParseMetaDevices(_, _)).WillByDefault(Return(metaDevices));
@@ -421,7 +421,7 @@ TEST_P(ExecNetworkGetMetricOtherTest, modelPriority_perfHint_exclusiveAsyncReq_t
EXPECT_CALL(*plugin, ParseMetaDevices(_, _)).Times(1);
EXPECT_CALL(*plugin, SelectDevice(_, _, _)).Times(1);
ON_CALL(*core, GetConfig(_, StrEq(GPU_CONFIG_KEY(MAX_NUM_THREADS)))).WillByDefault(Return(8));
ON_CALL(*core, GetConfig(_, StrEq(ov::compilation_num_threads.name()))).WillByDefault(Return(8));
ON_CALL(*core,
LoadNetwork(::testing::Matcher<const InferenceEngine::CNNNetwork&>(_),
::testing::Matcher<const std::string&>(StrEq(CommonTestUtils::DEVICE_CPU)),