Take VPUX out of AUTO default candidate device list (#16037)

* 1. Add device blacklist for AUTO plugin.
2. Update the logic to parse out the device candidate list from the inputting config MULTI_DEVICE_PRIORITIES.
3. Update the corresponding mock test cases.
4. Ignore the GTEST warning for the test cases.

Signed-off-by: Wang, Yang <yang4.wang@intel.com>

* Update.

* Update.

* Update.

* Add description about blacklist.

* Apply suggestions from code review

Update.

Co-authored-by: yanlan song <bell.song@intel.com>

* Update.

* Apply suggestions from code review

Updated.

Co-authored-by: yanlan song <bell.song@intel.com>
Co-authored-by: River Li <river.li@intel.com>

* Update test case.

* Update test case.

* Update test case.

* Update.

* Update.

---------

Signed-off-by: Wang, Yang <yang4.wang@intel.com>
Co-authored-by: yanlan song <bell.song@intel.com>
Co-authored-by: River Li <river.li@intel.com>
Co-authored-by: Shen, Wanglei <wanglei.shen@intel.com>
This commit is contained in:
Wang, Yang 2023-03-21 17:46:44 +08:00 committed by GitHub
parent ec0a1e58d1
commit 5af4a8e8d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 162 additions and 111 deletions

View File

@ -850,83 +850,92 @@ std::string MultiDeviceInferencePlugin::GetDeviceList(const std::map<std::string
std::string allDevices;
auto deviceList = GetCore()->GetAvailableDevices();
auto deviceListConfig = config.find(ov::device::priorities.name());
if (deviceListConfig->second.empty()) {
for (auto&& device : deviceList) {
// filter out the supported devices
if (!_pluginConfig.isSupportedDevice(device))
continue;
allDevices += device + ",";
}
} else {
for (auto&& device : deviceList) {
// filter out the supported devices
if (!_pluginConfig.isSupportedDevice(device))
continue;
allDevices += device + ",";
}
std::vector<std::string> devicesMerged;
if (deviceListConfig != config.end() && !deviceListConfig->second.empty()) {
auto priorities = deviceListConfig->second;
// parsing the string and splitting the comma-separated tokens
std::vector<std::string> deviceVec = _pluginConfig.ParsePrioritiesDevices(priorities);
std::vector<std::string> devicesToBeDeleted;
auto updateDeviceVec = [&](const std::string& delPattern = "") {
auto iter = deviceVec.begin();
while (iter != deviceVec.end()) {
if (delPattern.empty()) {
if ((*iter).find("-") == 0) {
devicesToBeDeleted.push_back((*iter).erase(0, 1));
iter = deviceVec.erase(iter);
} else {
iter++;
}
} else {
if ((*iter).find(delPattern) != std::string::npos)
iter = deviceVec.erase(iter);
else
iter++;
}
}
std::vector<std::string> devicesToBeMerged = _pluginConfig.ParsePrioritiesDevices(priorities);
std::vector<std::string> devicesToBeDeleted(devicesToBeMerged.size());
const auto& iterDel = std::copy_if(devicesToBeMerged.begin(),
devicesToBeMerged.end(),
devicesToBeDeleted.begin(),
[](const std::string& item) {
return item.front() == '-';
});
devicesToBeDeleted.resize(std::distance(devicesToBeDeleted.begin(), iterDel));
const auto& iterMerge =
std::remove_if(devicesToBeMerged.begin(), devicesToBeMerged.end(), [](const std::string& item) {
return item.front() == '-';
});
devicesToBeMerged.resize(std::distance(devicesToBeMerged.begin(), iterMerge));
for (auto&& device : devicesToBeDeleted)
LOG_INFO_TAG("remove %s from device candidate list", device.c_str());
auto isAnyDev = [](std::string& device, const std::vector<std::string>& devices) {
auto iter = std::find_if(devices.begin(), devices.end(), [device](const std::string& devItem) {
return devItem.find(device) != std::string::npos;
});
return iter != devices.end();
};
updateDeviceVec();
if (devicesToBeDeleted.size() == 0) {
allDevices = deviceListConfig->second;
} else {
auto deviceNeedToMerge = [&](const std::string& devicename) {
for (auto&& iter : devicesToBeDeleted) {
if (iter.find(devicename) != std::string::npos)
return true;
}
return false;
};
auto mergeDeviceList = [&]() {
std::vector<std::string> mergedList;
auto prevSize = mergedList.size();
for (auto&& iter : deviceVec) {
for (auto&& viter : deviceList) {
if (viter.find(iter) != std::string::npos && deviceNeedToMerge(iter))
mergedList.push_back(std::move(viter));
}
// if virtual devices or mock devices
if (mergedList.size() == prevSize)
mergedList.push_back(std::move(iter));
prevSize = mergedList.size();
}
return mergedList;
};
deviceVec = deviceVec.size() == 0 ? deviceList : mergeDeviceList();
for (auto& iter : devicesToBeDeleted) {
LOG_INFO_TAG("remove %s from device candidate list", iter.c_str());
updateDeviceVec(iter);
}
for (auto&& device : deviceVec) {
if (!_pluginConfig.isSupportedDevice(device))
auto deviceWithDefaultID = [](std::string& device) {
// AUTO assume the default device ID will be "0" for the single device.
return device.find(".") == std::string::npos ? device + ".0" : device;
};
if (devicesToBeMerged.empty()) {
for (auto&& device : deviceList) {
if (isAnyDev(device, devicesToBeDeleted) || !_pluginConfig.isSupportedDevice(device))
continue;
allDevices += device + ",";
devicesMerged.push_back(device);
}
} else {
for (auto&& device : devicesToBeMerged) {
if (!isAnyDev(device, deviceList)) {
DeviceIDParser parsed{device};
auto iter = std::find(devicesMerged.begin(), devicesMerged.end(), parsed.getDeviceName());
if (iter != devicesMerged.end() && parsed.getDeviceName() != device && parsed.getDeviceID() == "0")
// The device is the device with default device ID (eg. GPU.0) and
// its wide name (eg. GPU) has been in device candidate list.
continue;
// Add user specified device into candidate list
devicesMerged.push_back(device);
} else {
// Update device name if supported device with id existed
for (auto&& item : deviceList) {
auto realDevice = deviceWithDefaultID(item);
if (isAnyDev(realDevice, devicesToBeDeleted) || item.find(device) == std::string::npos)
continue;
auto iter = std::find(devicesMerged.begin(), devicesMerged.end(), deviceWithDefaultID(item));
// Remove the device with default device id from candidate device list (eg. GPU.0)
// if its wide name is a single device (eg. GPU).
DeviceIDParser parsed{item};
if (parsed.getDeviceName() == item && iter != devicesMerged.end())
devicesMerged.erase(iter);
// continue if targe device has been in the candidate device list.
if (std::find(devicesMerged.begin(), devicesMerged.end(), item) != devicesMerged.end())
continue;
devicesMerged.push_back(item);
}
}
}
}
}
// remove the last ',' if exist
if (allDevices.back() == ',')
allDevices.pop_back();
if (devicesMerged.size()) {
allDevices.clear();
std::for_each(devicesMerged.begin(), devicesMerged.end(), [&allDevices](const std::string& device) {
allDevices += device + ",";
});
}
if (allDevices.empty()) {
IE_THROW() << "Please, check environment due to no supported devices can be used";
}
// remove the last ',' if exist
if (allDevices.back() == ',')
allDevices.pop_back();
return allDevices;
}

View File

@ -5,6 +5,10 @@
namespace MultiDevicePlugin {
const std::set<std::string> PluginConfig::_availableDevices = {"AUTO", "CPU", "GPU", "TEMPLATE", "NVIDIA", "VPUX", "MULTI", "HETERO", "mock"};
// AUTO will enable the blocklist if
// 1.No device priority passed to AUTO/MULTI.(eg. core.compile_model(model, "AUTO", configs);)
// 2.No valid device parsed out from device priority (eg. core.compile_model(model, "AUTO:-CPU,-GPU", configs);).
const std::set<std::string> PluginConfig::_deviceBlocklist = {"VPUX", "GNA"};
PluginConfig::PluginConfig() {
set_default();

View File

@ -205,7 +205,7 @@ public:
if ((realEndPos = realDevName.find('(')) != std::string::npos) {
realDevName = realDevName.substr(0, realEndPos);
}
if (_availableDevices.end() == std::find(_availableDevices.begin(), _availableDevices.end(), realDevName)) {
if (_deviceBlocklist.end() != std::find(_deviceBlocklist.begin(), _deviceBlocklist.end(), realDevName)) {
return false;
}
return true;
@ -217,17 +217,13 @@ public:
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);
if (!subStr.empty())
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);
if (!subStr.empty())
devices.push_back(subStr);
return devices;
}
@ -239,5 +235,6 @@ private:
std::map<std::string, BaseValidator::Ptr> property_validators;
BaseValidator::Ptr device_property_validator;
static const std::set<std::string> _availableDevices;
static const std::set<std::string> _deviceBlocklist;
};
} // namespace MultiDevicePlugin

View File

@ -23,6 +23,7 @@ using ::testing::Property;
using ::testing::Eq;
using ::testing::AnyNumber;
using ::testing::ReturnRef;
using ::testing::NiceMock;
using ::testing::AtLeast;
using ::testing::InvokeWithoutArgs;
using Config = std::map<std::string, std::string>;
@ -33,24 +34,35 @@ const char igpuFullDeviceName[] = "Intel(R) Gen9 HD Graphics (iGPU)";
const char dgpuFullDeviceName[] = "Intel(R) Iris(R) Xe MAX Graphics (dGPU)";
// const char myriadFullDeviceName[] = "Intel Movidius Myriad X VPU";
// const char vpuxFullDeviceName[] = "";
const std::vector<std::string> availableDevs = {"CPU", "GPU.0", "GPU.1", "VPUX", "UNSUPPORTED_DEVICE"};
const std::vector<std::string> availableDevs = {"CPU", "GPU", "VPUX"};
const std::vector<std::string> availableDevsWithId = {"CPU", "GPU.0", "GPU.1", "VPUX"};
using Params = std::tuple<std::string, std::string>;
using ConfigParams = std::tuple<
std::string, // Priority devices
std::string // expect metaDevices
std::vector<std::string>, // Available devices retrieved from Core
Params // Params {devicePriority, expect metaDevices}
>;
class GetDeviceListTest : public ::testing::TestWithParam<ConfigParams> {
public:
std::shared_ptr<MockICore> core;
std::shared_ptr<MockMultiDeviceInferencePlugin> plugin;
std::shared_ptr<NiceMock<MockICore>> core;
std::shared_ptr<NiceMock<MockMultiDeviceInferencePlugin>> plugin;
public:
static std::string getTestCaseName(testing::TestParamInfo<ConfigParams> obj) {
Params priorityAndMetaDev;
std::string priorityDevices;
std::string metaDevices;
std::tie(priorityDevices, metaDevices) = obj.param;
std::vector<std::string> availableDevices;
std::tie(availableDevices, priorityAndMetaDev) = obj.param;
std::tie(priorityDevices, metaDevices) = priorityAndMetaDev;
std::ostringstream result;
result << "priorityDevices_" << priorityDevices;
result << "_expectedDevices" << metaDevices;
result << "_availableDevicesList";
std::string devicesStr;
for (auto&& device : availableDevices) {
devicesStr += "_" + device;
}
result << devicesStr;
return result.str();
}
@ -61,15 +73,12 @@ public:
void SetUp() override {
// prepare mockicore and cnnNetwork for loading
core = std::shared_ptr<MockICore>(new MockICore());
auto* origin_plugin = new MockMultiDeviceInferencePlugin();
plugin = std::shared_ptr<MockMultiDeviceInferencePlugin>(origin_plugin);
core = std::shared_ptr<NiceMock<MockICore>>(new NiceMock<MockICore>());
auto* origin_plugin = new NiceMock<MockMultiDeviceInferencePlugin>();
plugin = std::shared_ptr<NiceMock<MockMultiDeviceInferencePlugin>>(origin_plugin);
// replace core with mock Icore
plugin->SetCore(core);
ON_CALL(*core, GetAvailableDevices()).WillByDefault(Return(availableDevs));
ON_CALL(*plugin, GetDeviceList).WillByDefault([this](
const std::map<std::string, std::string>& config) {
return plugin->MultiDeviceInferencePlugin::GetDeviceList(config);
@ -79,40 +88,72 @@ public:
TEST_P(GetDeviceListTest, GetDeviceListTestWithExcludeList) {
// get Parameter
Params priorityAndMetaDev;
std::string priorityDevices;
std::string metaDevices;
std::tie(priorityDevices, metaDevices) = this->GetParam();
std::vector<std::string> availableDevs;
std::tie(availableDevs, priorityAndMetaDev) = this->GetParam();
std::tie(priorityDevices, metaDevices) = priorityAndMetaDev;
//EXPECT_CALL(*plugin, GetDeviceList(_)).Times(1);
ON_CALL(*core, GetAvailableDevices()).WillByDefault(Return(availableDevs));
EXPECT_CALL(*core, GetAvailableDevices()).Times(1);
auto result = plugin->GetDeviceList({{ov::device::priorities.name(), priorityDevices}});
EXPECT_EQ(result, metaDevices);
}
const std::vector<Params> testConfigsWithId = {Params{" ", " "},
Params{"", "CPU,GPU.0,GPU.1"},
Params{"CPU, ", "CPU, "},
Params{" ,CPU", " ,CPU"},
Params{"CPU,", "CPU"},
Params{"CPU,,GPU", "CPU,GPU.0,GPU.1"},
Params{"CPU, ,GPU", "CPU, ,GPU.0,GPU.1"},
Params{"CPU,GPU,GPU.1", "CPU,GPU.0,GPU.1"},
Params{"CPU,GPU,VPUX,INVALID_DEVICE", "CPU,GPU.0,GPU.1,VPUX,INVALID_DEVICE"},
Params{"VPUX,GPU,CPU,-GPU.0", "VPUX,GPU.1,CPU"},
Params{"-GPU.0,GPU,CPU", "GPU.1,CPU"},
Params{"-GPU.0,GPU", "GPU.1"},
Params{"-GPU,GPU.0", "GPU.0"},
Params{"-GPU.0", "CPU,GPU.1"},
Params{"-GPU.0,-GPU.1", "CPU"},
Params{"-GPU.0,-GPU.1,INVALID_DEVICE", "INVALID_DEVICE"},
Params{"-GPU.0,-GPU.1,-INVALID_DEVICE", "CPU"},
Params{"-GPU.0,-CPU", "GPU.1"}};
// ConfigParams details
// example
// ConfigParams {devicePriority, expect metaDevices, ifThrowException}
const std::vector<Params> testConfigs = {Params{" ", " "},
Params{"", "CPU,GPU"},
Params{"GPU", "GPU"},
Params{"GPU.0", "GPU.0"},
Params{"GPU,GPU.0", "GPU"},
Params{"CPU", "CPU"},
Params{" ,CPU", " ,CPU"},
Params{" ,GPU", " ,GPU"},
Params{"GPU, ", "GPU, "},
Params{"CPU,GPU", "CPU,GPU"},
Params{"CPU,-GPU", "CPU"},
Params{"CPU,-GPU,GPU.0", "CPU,GPU.0"},
Params{"CPU,-GPU,GPU.1", "CPU,GPU.1"},
Params{"CPU,GPU,-GPU.0", "CPU"},
Params{"CPU,GPU,-GPU.1", "CPU,GPU"},
Params{"CPU,GPU.0,GPU", "CPU,GPU"},
Params{"CPU,GPU,GPU.0", "CPU,GPU"},
Params{"CPU,GPU,GPU.1", "CPU,GPU,GPU.1"},
Params{"CPU,GPU.1,GPU", "CPU,GPU.1,GPU"},
Params{"CPU,VPUX", "CPU,VPUX"},
Params{"CPU,-VPUX", "CPU"},
Params{"CPU,-INVALID_DEVICE", "CPU"},
Params{"CPU,GPU,VPUX", "CPU,GPU,VPUX"}};
const std::vector<ConfigParams> testConfigs = {
//
ConfigParams {"CPU,GPU,VPUX",
"CPU,GPU,VPUX"},
ConfigParams {"VPUX,GPU,CPU,-GPU.0",
"VPUX,GPU.1,CPU"},
ConfigParams {"-GPU.0,GPU,CPU",
"GPU.1,CPU"},
ConfigParams {"-GPU.0,GPU",
"GPU.1"},
ConfigParams {"-GPU.0", "CPU,GPU.1,VPUX"},
ConfigParams {"-GPU.0,-GPU.1", "CPU,VPUX"},
ConfigParams {"-GPU.0,-CPU", "GPU.1,VPUX"}
};
INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests_GetDeviceListWithID,
GetDeviceListTest,
::testing::Combine(::testing::Values(availableDevsWithId),
::testing::ValuesIn(testConfigsWithId)),
GetDeviceListTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, GetDeviceListTest,
::testing::ValuesIn(testConfigs),
GetDeviceListTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests_GetDeviceList,
GetDeviceListTest,
::testing::Combine(::testing::Values(availableDevs), ::testing::ValuesIn(testConfigs)),
GetDeviceListTest::getTestCaseName);
//toDo need add test for ParseMetaDevices(_, config) to check device config of
//return metaDevices