openvino/src/plugins/auto/tests/unit/select_device_test.cpp

304 lines
14 KiB
C++

// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <ie_metric_helpers.hpp>
#include <common_test_utils/test_constants.hpp>
#include "unit_test_utils/mocks/cpp_interfaces/interface/mock_icore.hpp"
#include "unit_test_utils/mocks/mock_iinfer_request.hpp"
#include "unit_test_utils/mocks/cpp_interfaces/impl/mock_inference_plugin_internal.hpp"
#include "unit_test_utils/mocks/cpp_interfaces/interface/mock_iexecutable_network_internal.hpp"
#include "unit_test_utils/mocks/cpp_interfaces/interface/mock_ivariable_state_internal.hpp"
#include "unit_test_utils/mocks/cpp_interfaces/interface/mock_iinference_plugin.hpp"
#include <ie_core.hpp>
#include <multi-device/multi_device_config.hpp>
#include <ngraph_functions/subgraph_builders.hpp>
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include "include/mock_auto_device_plugin.hpp"
#include "include/mock_common.hpp"
using ::testing::MatcherCast;
using ::testing::AllOf;
using ::testing::Throw;
using ::testing::Matches;
using ::testing::_;
using ::testing::StrEq;
using ::testing::Return;
using ::testing::Property;
using ::testing::Eq;
using ::testing::ReturnRef;
using ::testing::AtLeast;
using ::testing::InvokeWithoutArgs;
using ::testing::HasSubstr;
using Config = std::map<std::string, std::string>;
using namespace MockMultiDevice;
using ConfigParams = std::tuple<
std::string, // netPrecision
std::vector<DeviceInformation>, // metaDevices for select
DeviceInformation, // expect DeviceInformation
bool, // throw exception
bool, // enableDevicePriority
bool // reverse total device
>;
const DeviceInformation CPU_INFO = {CommonTestUtils::DEVICE_CPU, {}, 2, "01", "CPU_01"};
const DeviceInformation IGPU_INFO = {"GPU.0", {}, 2, "01", "iGPU_01"};
const DeviceInformation DGPU_INFO = {"GPU.1", {}, 2, "01", "dGPU_01"};
const DeviceInformation MYRIAD_INFO = {"MYRIAD", {}, 2, "01", "MYRIAD_01" };
const DeviceInformation NPU_INFO = {CommonTestUtils::DEVICE_KEEMBAY, {}, 2, "01", "NPU_01" };
const std::vector<DeviceInformation> fp32DeviceVector = {DGPU_INFO, IGPU_INFO, CPU_INFO, MYRIAD_INFO};
const std::vector<DeviceInformation> fp16DeviceVector = {DGPU_INFO, IGPU_INFO, MYRIAD_INFO, CPU_INFO};
const std::vector<DeviceInformation> int8DeviceVector = {NPU_INFO, DGPU_INFO, IGPU_INFO, CPU_INFO};
const std::vector<DeviceInformation> binDeviceVector = {DGPU_INFO, IGPU_INFO, CPU_INFO};
const std::vector<DeviceInformation> batchedblobDeviceVector = {DGPU_INFO, IGPU_INFO};
std::map<std::string, const std::vector<DeviceInformation>> devicesMap = {{"FP32", fp32DeviceVector},
{"FP16", fp16DeviceVector},
{"INT8", int8DeviceVector},
{"BIN", binDeviceVector},
{"BATCHED_BLOB", batchedblobDeviceVector}
};
const std::vector<DeviceInformation> totalDevices = {DGPU_INFO, IGPU_INFO, MYRIAD_INFO, CPU_INFO, NPU_INFO};
const std::vector<DeviceInformation> reverseTotalDevices = {NPU_INFO, CPU_INFO, MYRIAD_INFO, IGPU_INFO, DGPU_INFO};
const std::vector<std::string> netPrecisions = {"FP32", "FP16", "INT8", "BIN", "BATCHED_BLOB"};
std::vector<ConfigParams> testConfigs;
class SelectDeviceTest : public ::testing::TestWithParam<ConfigParams> {
public:
std::shared_ptr<MockICore> core;
std::shared_ptr<MockMultiDeviceInferencePlugin> plugin;
public:
static std::string getTestCaseName(testing::TestParamInfo<ConfigParams> obj) {
std::string netPrecision;
std::vector<DeviceInformation> devices;
DeviceInformation expect;
bool throwExcept;
bool enableDevicePriority;
bool reverse;
std::tie(netPrecision, devices, expect, throwExcept, enableDevicePriority, reverse) = obj.param;
std::ostringstream result;
result << "_netPrecision_" << netPrecision;
for (auto& item : devices) {
result << "_device_" << item.uniqueName;
}
result << "_expect_" << expect.uniqueName;
if (throwExcept) {
result << "_throwExcept_true";
} else {
result << "_throwExcept_false";
}
if (enableDevicePriority) {
result << "_enableDevicePriority_true";
} else {
result << "_enableDevicePriority_false";
}
if (reverse) {
result << "_reverseTotalDevice_true";
} else {
result << "_reverseTotalDevice_false";
}
return result.str();
}
// combine select_num devices from devices and make them to ConfigParams
// insert the ConfigParams into testConfigs
static void combine_device(const std::vector<DeviceInformation>& devices, size_t start,
size_t* result, size_t result_index, const size_t select_num, std::string& netPrecision,
bool enableDevicePriority, bool reverse) {
for (size_t i = start; i < devices.size() + 1 - result_index; i++) {
result[result_index - 1] = i;
if (result_index - 1 == 0) {
std::vector<DeviceInformation> metaDevices = {};
int devicePriority = 0;
for (int j = static_cast<int>(select_num) - 1; j >= 0; j--) {
auto tmpDevInfo = devices[result[j]];
if (enableDevicePriority) {
tmpDevInfo.devicePriority = devicePriority;
devicePriority++;
}
metaDevices.push_back(tmpDevInfo);
}
// Debug the combine_device
// for (auto& item : metaDevices) {
// std::cout << item.uniqueName << "_";
// }
// std::cout << netPrecision << std::endl;
auto& devicesInfo = devicesMap[netPrecision];
bool find = false;
DeviceInformation expect;
if (metaDevices.size() > 1) {
if (enableDevicePriority) {
std::vector<DeviceInformation> validDevices;
for (auto& item : devicesInfo) {
auto device = std::find_if(metaDevices.begin(), metaDevices.end(),
[&item](const DeviceInformation& d)->bool{return d.uniqueName == item.uniqueName;});
if (device != metaDevices.end()) {
validDevices.push_back(*device);
}
}
unsigned int currentDevicePriority = 100;
for (auto iter = validDevices.begin(); iter != validDevices.end(); iter++) {
if (iter->devicePriority < currentDevicePriority) {
expect = *iter;
currentDevicePriority = iter->devicePriority;
}
}
if (currentDevicePriority != 100) {
find = true;
}
} else {
for (auto& item : devicesInfo) {
auto device = std::find_if(metaDevices.begin(), metaDevices.end(),
[&item](const DeviceInformation& d)->bool{return d.uniqueName == item.uniqueName;});
if (device != metaDevices.end()) {
find = true;
expect = item;
break;
}
}
}
} else if (metaDevices.size() == 1) {
find = true;
expect = metaDevices[0];
} else {
find = false;
}
testConfigs.push_back(std::make_tuple(netPrecision, metaDevices,
expect, !find, enableDevicePriority, reverse));
} else {
combine_device(devices, i + 1, result, result_index - 1,
select_num, netPrecision, enableDevicePriority, reverse);
}
}
}
static std::vector<ConfigParams> CreateConfigs() {
auto result = new size_t[totalDevices.size()];
// test all netPrecision with all possible combine devices
// netPrecision number is 5
// device number is 5
// combine devices is 5!/5! + 5!/(4!*1!) + 5!/(3!*2!) + 5!/(2!*3!) + 5(1!*4!) = 31
// null device 1
// total test config num is 32*5 = 160
for (auto netPrecision : netPrecisions) {
for (size_t i = 1; i <= totalDevices.size(); i++) {
combine_device(totalDevices, 0, result, i, i, netPrecision, false, false);
}
// test null device
testConfigs.push_back(ConfigParams{netPrecision, {}, {}, true, false, false});
}
// reverse totalDevices for test
for (auto netPrecision : netPrecisions) {
for (size_t i = 1; i <= reverseTotalDevices.size(); i++) {
combine_device(reverseTotalDevices, 0, result, i, i, netPrecision, false, true);
}
}
// add test for enableDevicePriority
// test case num is 31*5 = 155
for (auto netPrecision : netPrecisions) {
for (size_t i = 1; i <= totalDevices.size(); i++) {
combine_device(totalDevices, 0, result, i, i, netPrecision, true, false);
}
}
// reverse totalDevices for test
for (auto netPrecision : netPrecisions) {
for (size_t i = 1; i <= reverseTotalDevices.size(); i++) {
combine_device(reverseTotalDevices, 0, result, i, i, netPrecision, true, true);
}
}
delete []result;
return testConfigs;
}
void compare(DeviceInformation& a, DeviceInformation& b) {
EXPECT_EQ(a.deviceName, b.deviceName);
EXPECT_EQ(a.uniqueName, b.uniqueName);
EXPECT_EQ(a.defaultDeviceID, b.defaultDeviceID);
}
void TearDown() override {
core.reset();
plugin.reset();
}
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);
// replace core with mock Icore
plugin->SetCore(core);
IE_SET_METRIC(OPTIMIZATION_CAPABILITIES, cpuCability, {"FP32", "FP16", "INT8", "BIN"});
IE_SET_METRIC(OPTIMIZATION_CAPABILITIES, gpuCability, {"FP32", "FP16", "BATCHED_BLOB", "BIN", "INT8"});
IE_SET_METRIC(OPTIMIZATION_CAPABILITIES, myriadCability, {"FP16"});
IE_SET_METRIC(OPTIMIZATION_CAPABILITIES, npuCability, {"INT8"});
IE_SET_METRIC(DEVICE_ARCHITECTURE, gpuArchitecture, "GPU: vendor=0x8086 arch=0");
IE_SET_METRIC(DEVICE_TYPE, dGpuType, Metrics::DeviceType::discrete);
IE_SET_METRIC(DEVICE_TYPE, iGpuType, Metrics::DeviceType::integrated);
ON_CALL(*core, GetMetric(StrEq(CommonTestUtils::DEVICE_CPU),
StrEq(METRIC_KEY(OPTIMIZATION_CAPABILITIES)), _)).WillByDefault(RETURN_MOCK_VALUE(cpuCability));
ON_CALL(*core, GetMetric(HasSubstr("GPU"),
StrEq(METRIC_KEY(OPTIMIZATION_CAPABILITIES)), _)).WillByDefault(RETURN_MOCK_VALUE(gpuCability));
ON_CALL(*core, GetMetric(StrEq("MYRIAD"),
StrEq(METRIC_KEY(OPTIMIZATION_CAPABILITIES)), _)).WillByDefault(RETURN_MOCK_VALUE(myriadCability));
ON_CALL(*core, GetMetric(StrEq(CommonTestUtils::DEVICE_KEEMBAY),
StrEq(METRIC_KEY(OPTIMIZATION_CAPABILITIES)), _)).WillByDefault(RETURN_MOCK_VALUE(npuCability));
ON_CALL(*core, GetMetric(HasSubstr("GPU"),
StrEq(METRIC_KEY(DEVICE_ARCHITECTURE)), _)).WillByDefault(RETURN_MOCK_VALUE(gpuArchitecture));
ON_CALL(*core, GetMetric(StrEq("GPU"),
StrEq(METRIC_KEY(DEVICE_TYPE)), _)).WillByDefault(RETURN_MOCK_VALUE(iGpuType));
ON_CALL(*core, GetMetric(StrEq("GPU.0"),
StrEq(METRIC_KEY(DEVICE_TYPE)), _)).WillByDefault(RETURN_MOCK_VALUE(iGpuType));
ON_CALL(*core, GetMetric(StrEq("GPU.1"),
StrEq(METRIC_KEY(DEVICE_TYPE)), _)).WillByDefault(RETURN_MOCK_VALUE(dGpuType));
ON_CALL(*plugin, SelectDevice).WillByDefault([this](const std::vector<DeviceInformation>& metaDevices,
const std::string& netPrecision, unsigned int priority) {
return plugin->MultiDeviceInferencePlugin::SelectDevice(metaDevices, netPrecision, priority);
});
ON_CALL(*plugin, GetValidDevice)
.WillByDefault([this](const std::vector<DeviceInformation>& metaDevices, const std::string& netPrecision) {
return plugin->MultiDeviceInferencePlugin::GetValidDevice(metaDevices, netPrecision);
});
}
};
TEST_P(SelectDeviceTest, SelectDevice) {
// get Parameter
std::string netPrecision;
std::vector<DeviceInformation> devices;
DeviceInformation expect;
bool throwExcept;
bool enableDevicePriority;
bool reverse;
std::tie(netPrecision, devices, expect, throwExcept, enableDevicePriority, reverse) = this->GetParam();
EXPECT_CALL(*plugin, SelectDevice(_, _, _)).Times(1);
if (devices.size() >= 1) {
EXPECT_CALL(*core, GetMetric(_, _, _)).Times(AtLeast(static_cast<int>(devices.size()) - 1));
} else {
EXPECT_CALL(*core, GetMetric(_, _, _)).Times(0);
}
if (throwExcept) {
ASSERT_THROW(plugin->SelectDevice(devices, netPrecision, 0), InferenceEngine::Exception);
} else {
auto result = plugin->SelectDevice(devices, netPrecision, 0);
compare(result, expect);
}
}
INSTANTIATE_TEST_SUITE_P(smoke_Auto_BehaviorTests, SelectDeviceTest,
::testing::ValuesIn(SelectDeviceTest::CreateConfigs()),
SelectDeviceTest::getTestCaseName);