enable new property ov::hint::use_hyper_threading (#16176)
* enable apply_processor_type() * declare PROCESSOR_TYPE * enable readProperties * test case for get_property() * enable set_property() and test cases * reduce changes * fix code style issue * fix python test case issue * remove python interface * move processor type definition out of dev_api * refine coding * add dependency * update header file * update description * merge intel_cpu header file * add inline in-code documentation * change 'UNDEFINED' to 'DEFAULT' * remove ProcTypeConfig * refine change * refine change * enable new property use hyper threading * update description * resume legacy code * change to ov::hint namespace * update including header file * update C API and Python API * update description for comments * update test case for comments * update function location for comments * fix typo * fix typo * fix code style issue and update test case * move cpu_map_scheduling into threading folder
This commit is contained in:
parent
aa0df8e535
commit
815d4abc03
@ -119,6 +119,13 @@ ov_property_key_affinity;
|
||||
OPENVINO_C_VAR(const char*)
|
||||
ov_property_key_inference_num_threads;
|
||||
|
||||
/**
|
||||
* @brief Read-write property, it is high-level OpenVINO hint for using hyper threading processors during CPU inference
|
||||
* @ingroup ov_property_c_api
|
||||
*/
|
||||
OPENVINO_C_VAR(const char*)
|
||||
ov_property_key_hint_use_hyper_threading;
|
||||
|
||||
/**
|
||||
* @brief Read-write property, it is high-level OpenVINO Performance Hints
|
||||
* @ingroup ov_property_c_api
|
||||
|
@ -23,6 +23,7 @@ const char* ov_property_key_num_streams = "NUM_STREAMS";
|
||||
const char* ov_property_key_affinity = "AFFINITY";
|
||||
const char* ov_property_key_inference_num_threads = "INFERENCE_NUM_THREADS";
|
||||
const char* ov_property_key_hint_performance_mode = "PERFORMANCE_HINT";
|
||||
const char* ov_property_key_hint_use_hyper_threading = "USE_HYPER_THREADING";
|
||||
const char* ov_property_key_hint_inference_precision = "INFERENCE_PRECISION_HINT";
|
||||
const char* ov_property_key_hint_num_requests = "PERFORMANCE_HINT_NUM_REQUESTS";
|
||||
const char* ov_property_key_hint_model_priority = "MODEL_PRIORITY";
|
||||
|
@ -259,6 +259,22 @@ TEST_P(ov_core_test, ov_core_set_property_enum_invalid) {
|
||||
OV_EXPECT_OK(ov_core_get_property(core, device_name.c_str(), key, &ret));
|
||||
EXPECT_STRNE(invalid_mode, ret);
|
||||
ov_free(ret);
|
||||
|
||||
const char* key_ht = ov_property_key_hint_use_hyper_threading;
|
||||
const char* val_ht = "YES";
|
||||
OV_EXPECT_OK(ov_core_set_property(core, device_name.c_str(), key_ht, val_ht));
|
||||
ret = nullptr;
|
||||
OV_EXPECT_OK(ov_core_get_property(core, device_name.c_str(), key_ht, &ret));
|
||||
EXPECT_STREQ(val_ht, ret);
|
||||
ov_free(ret);
|
||||
|
||||
const char* invalid_val = "INVALID_VAL";
|
||||
OV_EXPECT_NOT_OK(ov_core_set_property(core, device_name.c_str(), key_ht, invalid_val));
|
||||
ret = nullptr;
|
||||
OV_EXPECT_OK(ov_core_get_property(core, device_name.c_str(), key_ht, &ret));
|
||||
EXPECT_STRNE(invalid_val, ret);
|
||||
ov_free(ret);
|
||||
|
||||
ov_core_free(core);
|
||||
}
|
||||
|
||||
@ -276,6 +292,14 @@ TEST_P(ov_core_test, ov_core_set_and_get_property_enum) {
|
||||
EXPECT_STREQ(affinity, ret);
|
||||
ov_free(ret);
|
||||
|
||||
const char* key_ht = ov_property_key_hint_use_hyper_threading;
|
||||
const char* val_ht = "YES";
|
||||
OV_EXPECT_OK(ov_core_set_property(core, device_name.c_str(), key_ht, val_ht));
|
||||
ret = nullptr;
|
||||
OV_EXPECT_OK(ov_core_get_property(core, device_name.c_str(), key_ht, &ret));
|
||||
EXPECT_STREQ(val_ht, ret);
|
||||
ov_free(ret);
|
||||
|
||||
ov_core_free(core);
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,7 @@ void regmodule_properties(py::module m) {
|
||||
wrap_property_RW(m_hint, ov::hint::inference_precision, "inference_precision");
|
||||
wrap_property_RW(m_hint, ov::hint::model_priority, "model_priority");
|
||||
wrap_property_RW(m_hint, ov::hint::performance_mode, "performance_mode");
|
||||
wrap_property_RW(m_hint, ov::hint::use_hyper_threading, "use_hyper_threading");
|
||||
wrap_property_RW(m_hint, ov::hint::execution_mode, "execution_mode");
|
||||
wrap_property_RW(m_hint, ov::hint::num_requests, "num_requests");
|
||||
wrap_property_RW(m_hint, ov::hint::model, "model");
|
||||
|
@ -219,6 +219,16 @@ def test_properties_ro(ov_property_ro, expected_value):
|
||||
"PERFORMANCE_HINT",
|
||||
((properties.hint.PerformanceMode.UNDEFINED, properties.hint.PerformanceMode.UNDEFINED),),
|
||||
),
|
||||
(
|
||||
properties.hint.use_hyper_threading,
|
||||
"USE_HYPER_THREADING",
|
||||
(
|
||||
(True, True),
|
||||
(False, False),
|
||||
(1, True),
|
||||
(0, False),
|
||||
),
|
||||
),
|
||||
(
|
||||
properties.hint.execution_mode,
|
||||
"EXECUTION_MODE_HINT",
|
||||
@ -399,6 +409,7 @@ def test_single_property_setting(device):
|
||||
properties.affinity(properties.Affinity.NONE),
|
||||
properties.inference_precision(Type.f32),
|
||||
properties.hint.performance_mode(properties.hint.PerformanceMode.LATENCY),
|
||||
properties.hint.use_hyper_threading(True),
|
||||
properties.hint.num_requests(12),
|
||||
properties.streams.num(5),
|
||||
],
|
||||
@ -411,6 +422,7 @@ def test_single_property_setting(device):
|
||||
properties.affinity(): properties.Affinity.NONE,
|
||||
properties.inference_precision(): Type.f32,
|
||||
properties.hint.performance_mode(): properties.hint.PerformanceMode.LATENCY,
|
||||
properties.hint.use_hyper_threading(): True,
|
||||
properties.hint.num_requests(): 12,
|
||||
properties.streams.num(): 5,
|
||||
},
|
||||
|
@ -0,0 +1,29 @@
|
||||
// Copyright (C) 2018-2023 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
/**
|
||||
* @brief A header file for CPU map scheduling
|
||||
* @file cpu_map_scheduling.hpp
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "openvino/runtime/properties.hpp"
|
||||
|
||||
namespace ov {
|
||||
|
||||
/**
|
||||
* @brief Limit available CPU resource in processors type table according to hyper threading property
|
||||
* @param[in] input_type indicate value of property use_hyper_threading.
|
||||
* @param[in] input_changed indicate if value is set by user.
|
||||
* @param[in] proc_type_table candidate processors available at this time
|
||||
* @return updated proc_type_table which removed unmatched processors
|
||||
*/
|
||||
std::vector<std::vector<int>> apply_hyper_threading(bool input_type,
|
||||
const bool input_changed,
|
||||
const std::vector<std::vector<int>> proc_type_table);
|
||||
|
||||
} // namespace ov
|
@ -351,6 +351,22 @@ inline std::istream& operator>>(std::istream& is, PerformanceMode& performance_m
|
||||
*/
|
||||
static constexpr Property<PerformanceMode> performance_mode{"PERFORMANCE_HINT"};
|
||||
|
||||
/**
|
||||
* @brief This property allows hyper threading during inference.
|
||||
* @ingroup ov_runtime_cpp_prop_api
|
||||
*
|
||||
* Developer can use this property to use or not use hyper threading during inference. If user does not explicitly set
|
||||
* value for this property, OpenVINO may choose any desired value based on internal logic.
|
||||
*
|
||||
* The following code is example to use this property.
|
||||
*
|
||||
* @code
|
||||
* ie.set_property(ov::hint::use_hyper_threading(true));
|
||||
* ie.set_property(ov::hint::use_hyper_threading(false));
|
||||
* @endcode
|
||||
*/
|
||||
static constexpr Property<bool> use_hyper_threading{"USE_HYPER_THREADING"};
|
||||
|
||||
/**
|
||||
* @brief (Optional) property that backs the (above) Performance Hints
|
||||
* by giving additional information on how many inference requests the application will be keeping in flight
|
||||
|
28
src/inference/src/dev/threading/cpu_map_scheduling.cpp
Normal file
28
src/inference/src/dev/threading/cpu_map_scheduling.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright (C) 2018-2023 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "openvino/runtime/threading/cpu_map_scheduling.hpp"
|
||||
|
||||
#include "ie_system_conf.h"
|
||||
|
||||
namespace ov {
|
||||
|
||||
std::vector<std::vector<int>> apply_hyper_threading(bool input_value,
|
||||
const bool input_changed,
|
||||
const std::vector<std::vector<int>> proc_type_table) {
|
||||
std::vector<std::vector<int>> result_table = proc_type_table;
|
||||
|
||||
if ((proc_type_table[0][HYPER_THREADING_PROC] > 0) &&
|
||||
(((!input_value) && input_changed) || ((!input_changed) && (proc_type_table.size() > 1)))) {
|
||||
for (auto& i : result_table) {
|
||||
i[ALL_PROC] -= i[HYPER_THREADING_PROC];
|
||||
i[HYPER_THREADING_PROC] = 0;
|
||||
}
|
||||
input_value = false;
|
||||
}
|
||||
|
||||
return result_table;
|
||||
}
|
||||
|
||||
} // namespace ov
|
@ -78,6 +78,17 @@ void Config::readProperties(const std::map<std::string, std::string> &prop) {
|
||||
streamExecutorConfig.SetConfig(key, val);
|
||||
} else if (hintsConfigKeys.end() != std::find(hintsConfigKeys.begin(), hintsConfigKeys.end(), key)) {
|
||||
perfHintsConfig.SetConfig(key, val);
|
||||
} else if (key == ov::hint::use_hyper_threading.name()) {
|
||||
if (val == PluginConfigParams::YES) {
|
||||
useHyperThreading = true;
|
||||
changedHyperThreading = true;
|
||||
} else if (val == PluginConfigParams::NO) {
|
||||
useHyperThreading = false;
|
||||
changedHyperThreading = true;
|
||||
} else {
|
||||
IE_THROW() << "Wrong value " << val << "for property key " << ov::hint::use_hyper_threading.name()
|
||||
<< ". Expected only true/false." << std::endl;
|
||||
}
|
||||
} else if (key == PluginConfigParams::KEY_DYN_BATCH_LIMIT) {
|
||||
int val_i = -1;
|
||||
try {
|
||||
|
@ -49,6 +49,8 @@ struct Config {
|
||||
size_t rtCacheCapacity = 5000ul;
|
||||
InferenceEngine::IStreamsExecutor::Config streamExecutorConfig;
|
||||
InferenceEngine::PerfHintsConfig perfHintsConfig;
|
||||
bool useHyperThreading = true;
|
||||
bool changedHyperThreading = false;
|
||||
#if defined(OPENVINO_ARCH_X86) || defined(OPENVINO_ARCH_X86_64)
|
||||
LPTransformsMode lpTransformsMode = LPTransformsMode::On;
|
||||
bool enforceBF16 = true;
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
namespace ov {
|
||||
namespace intel_cpu {
|
||||
|
||||
/**
|
||||
* @brief Generate streams information table according to processors type table.
|
||||
* @param[in] input_streams is the targeted number of streams set by user via ov::num_streams or hints.
|
||||
@ -41,4 +42,4 @@ std::vector<std::vector<int>> get_streams_info_table(const int input_streams,
|
||||
const int model_prefer_threads,
|
||||
const std::vector<std::vector<int>> proc_type_table);
|
||||
} // namespace intel_cpu
|
||||
} // namespace ov
|
||||
} // namespace ov
|
@ -308,6 +308,7 @@ InferenceEngine::Parameter ExecNetwork::GetMetric(const std::string &name) const
|
||||
RO_property(ov::inference_precision.name()),
|
||||
RO_property(ov::hint::performance_mode.name()),
|
||||
RO_property(ov::hint::num_requests.name()),
|
||||
RO_property(ov::hint::use_hyper_threading.name()),
|
||||
RO_property(ov::execution_devices.name()),
|
||||
};
|
||||
}
|
||||
@ -348,6 +349,9 @@ InferenceEngine::Parameter ExecNetwork::GetMetric(const std::string &name) const
|
||||
} else if (name == ov::hint::performance_mode) {
|
||||
const auto perfHint = ov::util::from_string(config.perfHintsConfig.ovPerfHint, ov::hint::performance_mode);
|
||||
return perfHint;
|
||||
} else if (name == ov::hint::use_hyper_threading.name()) {
|
||||
const bool use_ht = config.useHyperThreading;
|
||||
return decltype(ov::hint::use_hyper_threading)::value_type(use_ht);
|
||||
} else if (name == ov::hint::num_requests) {
|
||||
const auto perfHintNumRequests = config.perfHintsConfig.ovPerfHintNumRequests;
|
||||
return decltype(ov::hint::num_requests)::value_type(perfHintNumRequests);
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include <ie_ngraph_utils.hpp>
|
||||
|
||||
#include "performance_heuristics.hpp"
|
||||
|
||||
#include "openvino/runtime/properties.hpp"
|
||||
#include "weights_cache.hpp"
|
||||
#include "utils/denormals.hpp"
|
||||
|
||||
@ -514,6 +514,9 @@ Parameter Engine::GetConfig(const std::string& name, const std::map<std::string,
|
||||
} else if (name == ov::hint::performance_mode) {
|
||||
const auto perfHint = ov::util::from_string(engConfig.perfHintsConfig.ovPerfHint, ov::hint::performance_mode);
|
||||
return perfHint;
|
||||
} else if (name == ov::hint::use_hyper_threading) {
|
||||
const bool ht_value = engConfig.useHyperThreading;
|
||||
return decltype(ov::hint::use_hyper_threading)::value_type(ht_value);
|
||||
} else if (name == ov::hint::num_requests) {
|
||||
const auto perfHintNumRequests = engConfig.perfHintsConfig.ovPerfHintNumRequests;
|
||||
return decltype(ov::hint::num_requests)::value_type(perfHintNumRequests);
|
||||
@ -602,6 +605,7 @@ Parameter Engine::GetMetric(const std::string& name, const std::map<std::string,
|
||||
RW_property(ov::inference_precision.name()),
|
||||
RW_property(ov::hint::performance_mode.name()),
|
||||
RW_property(ov::hint::num_requests.name()),
|
||||
RW_property(ov::hint::use_hyper_threading.name()),
|
||||
RW_property(ov::device::id.name()),
|
||||
};
|
||||
|
||||
|
@ -48,6 +48,10 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
smoke_OVClassGetMetricTest, OVClassGetMetricTest_FULL_DEVICE_NAME,
|
||||
::testing::Values("CPU", "MULTI", "HETERO", "AUTO"));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(smoke_OVClassSetConfigTest,
|
||||
OVClassSetUseHyperThreadingHintConfigTest,
|
||||
::testing::Values("CPU"));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
smoke_OVClassGetMetricTest, OVClassGetMetricTest_OPTIMIZATION_CAPABILITIES,
|
||||
::testing::Values("CPU"));
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <ie_system_conf.h>
|
||||
|
||||
#include <common_test_utils/test_common.hpp>
|
||||
#include <openvino/runtime/threading/cpu_map_scheduling.hpp>
|
||||
|
||||
#include "cpu_streams_calculation.hpp"
|
||||
|
||||
@ -15,6 +16,96 @@ using namespace ov;
|
||||
|
||||
namespace {
|
||||
|
||||
struct UseHTTestCase {
|
||||
bool use_ht_value;
|
||||
bool use_ht_changed;
|
||||
std::vector<std::vector<int>> proc_type_table;
|
||||
std::vector<std::vector<int>> result_table;
|
||||
};
|
||||
|
||||
class UseHTTests : public CommonTestUtils::TestsCommon, public testing::WithParamInterface<std::tuple<UseHTTestCase>> {
|
||||
public:
|
||||
void SetUp() override {
|
||||
const auto& test_data = std::get<0>(GetParam());
|
||||
|
||||
std::vector<std::vector<int>> test_result_table =
|
||||
ov::apply_hyper_threading(test_data.use_ht_value,
|
||||
test_data.use_ht_changed,
|
||||
test_data.proc_type_table);
|
||||
|
||||
ASSERT_EQ(test_data.result_table, test_result_table);
|
||||
}
|
||||
};
|
||||
|
||||
UseHTTestCase _2sockets_false = {
|
||||
false,
|
||||
true,
|
||||
{{208, 104, 0, 104}, {104, 52, 0, 52}, {104, 52, 0, 52}},
|
||||
{{104, 104, 0, 0}, {52, 52, 0, 0}, {52, 52, 0, 0}},
|
||||
};
|
||||
|
||||
UseHTTestCase _2sockets_true = {
|
||||
true,
|
||||
true,
|
||||
{{208, 104, 0, 104}, {104, 52, 0, 52}, {104, 52, 0, 52}},
|
||||
{{208, 104, 0, 104}, {104, 52, 0, 52}, {104, 52, 0, 52}},
|
||||
};
|
||||
|
||||
UseHTTestCase _2sockets_default_1 = {
|
||||
false,
|
||||
false,
|
||||
{{208, 104, 0, 104}, {104, 52, 0, 52}, {104, 52, 0, 52}},
|
||||
{{104, 104, 0, 0}, {52, 52, 0, 0}, {52, 52, 0, 0}},
|
||||
};
|
||||
|
||||
UseHTTestCase _2sockets_default_2 = {
|
||||
true,
|
||||
false,
|
||||
{{208, 104, 0, 104}, {104, 52, 0, 52}, {104, 52, 0, 52}},
|
||||
{{104, 104, 0, 0}, {52, 52, 0, 0}, {52, 52, 0, 0}},
|
||||
};
|
||||
|
||||
UseHTTestCase _1sockets_false = {
|
||||
false,
|
||||
true,
|
||||
{{20, 6, 8, 6}},
|
||||
{{14, 6, 8, 0}},
|
||||
};
|
||||
|
||||
UseHTTestCase _1sockets_true = {
|
||||
true,
|
||||
true,
|
||||
{{20, 6, 8, 6}},
|
||||
{{20, 6, 8, 6}},
|
||||
};
|
||||
|
||||
UseHTTestCase _1sockets_default_1 = {
|
||||
false,
|
||||
false,
|
||||
{{20, 6, 8, 6}},
|
||||
{{20, 6, 8, 6}},
|
||||
};
|
||||
|
||||
UseHTTestCase _1sockets_default_2 = {
|
||||
true,
|
||||
false,
|
||||
{{20, 6, 8, 6}},
|
||||
{{20, 6, 8, 6}},
|
||||
};
|
||||
|
||||
TEST_P(UseHTTests, UseHT) {}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(UseHTTable,
|
||||
UseHTTests,
|
||||
testing::Values(_2sockets_false,
|
||||
_2sockets_true,
|
||||
_2sockets_default_1,
|
||||
_2sockets_default_2,
|
||||
_1sockets_false,
|
||||
_1sockets_true,
|
||||
_1sockets_default_1,
|
||||
_1sockets_default_2));
|
||||
|
||||
struct StreamsCalculationTestCase {
|
||||
int input_streams;
|
||||
int input_threads;
|
||||
|
@ -121,6 +121,7 @@ using OVClassLoadNetworkTest = OVClassQueryNetworkTest;
|
||||
using OVClassSetGlobalConfigTest = OVClassBaseTestP;
|
||||
using OVClassSetModelPriorityConfigTest = OVClassBaseTestP;
|
||||
using OVClassSetExecutionModeHintConfigTest = OVClassBaseTestP;
|
||||
using OVClassSetUseHyperThreadingHintConfigTest = OVClassBaseTestP;
|
||||
using OVClassSetTBBForceTerminatePropertyTest = OVClassBaseTestP;
|
||||
using OVClassSetLogLevelConfigTest = OVClassBaseTestP;
|
||||
using OVClassSpecificDeviceTestSetConfig = OVClassBaseTestP;
|
||||
@ -611,6 +612,23 @@ TEST_P(OVClassSetExecutionModeHintConfigTest, SetConfigNoThrow) {
|
||||
ASSERT_EQ(ov::hint::ExecutionMode::PERFORMANCE, ie.get_property(target_device, ov::hint::execution_mode));
|
||||
}
|
||||
|
||||
TEST_P(OVClassSetUseHyperThreadingHintConfigTest, SetConfigNoThrow) {
|
||||
ov::Core ie = createCoreWithTemplate();
|
||||
|
||||
OV_ASSERT_PROPERTY_SUPPORTED(ov::hint::use_hyper_threading);
|
||||
|
||||
bool defaultMode{};
|
||||
ASSERT_NO_THROW(defaultMode = ie.get_property(target_device, ov::hint::use_hyper_threading));
|
||||
(void)defaultMode;
|
||||
|
||||
ASSERT_EQ(true, ie.get_property(target_device, ov::hint::use_hyper_threading));
|
||||
|
||||
ie.set_property(target_device, ov::hint::use_hyper_threading(false));
|
||||
ASSERT_EQ(false, ie.get_property(target_device, ov::hint::use_hyper_threading));
|
||||
ie.set_property(target_device, ov::hint::use_hyper_threading(true));
|
||||
ASSERT_EQ(true, ie.get_property(target_device, ov::hint::use_hyper_threading));
|
||||
}
|
||||
|
||||
TEST_P(OVClassSetDevicePriorityConfigTest, SetConfigAndCheckGetConfigNoThrow) {
|
||||
ov::Core ie = createCoreWithTemplate();
|
||||
std::string devicePriority;
|
||||
|
Loading…
Reference in New Issue
Block a user