Add Core property to switch from mmap to read in IR Frontend (#16600)

* Add Core property to switch from `mmap` to `read`
in IR FrontEnd

* Add tests on `ov::enable_mmap` property

* Add `enable_mmap` in C & Py APIs

* ClangFormat
This commit is contained in:
Vitaliy Urusovskij 2023-04-05 18:22:11 +04:00 committed by GitHub
parent fef04e468a
commit 7442a17240
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 115 additions and 51 deletions

View File

@ -206,3 +206,17 @@ ov_property_key_device_priorities;
*/ */
OPENVINO_C_VAR(const char*) OPENVINO_C_VAR(const char*)
ov_property_key_hint_execution_mode; ov_property_key_hint_execution_mode;
/**
* @brief Read-write property to set whether force terminate tbb when ov core destruction
* @ingroup ov_property_c_api
*/
OPENVINO_C_VAR(const char*)
ov_property_key_force_tbb_terminate;
/**
* @brief Read-write property to configure `mmap()` use for model read
* @ingroup ov_property_c_api
*/
OPENVINO_C_VAR(const char*)
ov_property_key_enable_mmap;

View File

@ -33,3 +33,5 @@ const char* ov_property_key_log_level = "LOG_LEVEL";
const char* ov_property_key_enable_profiling = "PERF_COUNT"; const char* ov_property_key_enable_profiling = "PERF_COUNT";
const char* ov_property_key_device_priorities = "MULTI_DEVICE_PRIORITIES"; const char* ov_property_key_device_priorities = "MULTI_DEVICE_PRIORITIES";
const char* ov_property_key_hint_execution_mode = "EXECUTION_MODE_HINT"; const char* ov_property_key_hint_execution_mode = "EXECUTION_MODE_HINT";
const char* ov_property_key_force_tbb_terminate = "FORCE_TBB_TERMINATE";
const char* ov_property_key_enable_mmap = "ENABLE_MMAP";

View File

@ -312,55 +312,38 @@ TEST_P(ov_core_test, ov_core_set_and_get_property_enum) {
OV_EXPECT_OK(ov_core_create(&core)); OV_EXPECT_OK(ov_core_create(&core));
EXPECT_NE(nullptr, core); EXPECT_NE(nullptr, core);
const char* key = ov_property_key_hint_performance_mode; std::map<const char*, const char*> properties = {{ov_property_key_hint_performance_mode, "LATENCY"},
const char* affinity = "LATENCY"; {ov_property_key_hint_scheduling_core_type, "PCORE_ONLY"},
OV_EXPECT_OK(ov_core_set_property(core, device_name.c_str(), key, affinity)); {ov_property_key_hint_enable_hyper_threading, "YES"},
{ov_property_key_enable_profiling, "YES"}};
for (const auto& property : properties) {
OV_EXPECT_OK(ov_core_set_property(core, device_name.c_str(), property.first, property.second));
char* ret = nullptr; char* ret = nullptr;
OV_EXPECT_OK(ov_core_get_property(core, device_name.c_str(), key, &ret)); OV_EXPECT_OK(ov_core_get_property(core, device_name.c_str(), property.first, &ret));
EXPECT_STREQ(affinity, ret); EXPECT_STREQ(property.second, ret);
ov_free(ret);
const char* key_pin = ov_property_key_hint_enable_cpu_pinning;
const char* val_pin = "YES";
OV_EXPECT_OK(ov_core_set_property(core, device_name.c_str(), key_pin, val_pin));
ret = nullptr;
OV_EXPECT_OK(ov_core_get_property(core, device_name.c_str(), key_pin, &ret));
EXPECT_STREQ(val_pin, ret);
ov_free(ret);
const char* key_type = ov_property_key_hint_scheduling_core_type;
const char* val_type = "PCORE_ONLY";
OV_EXPECT_OK(ov_core_set_property(core, device_name.c_str(), key_type, val_type));
ret = nullptr;
OV_EXPECT_OK(ov_core_get_property(core, device_name.c_str(), key_type, &ret));
EXPECT_STREQ(val_type, ret);
ov_free(ret);
const char* key_ht = ov_property_key_hint_enable_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_free(ret);
}
ov_core_free(core); ov_core_free(core);
} }
TEST_P(ov_core_test, ov_core_set_and_get_property_bool) { TEST_F(ov_core_test, ov_core_set_and_get_property_no_device) {
auto device_name = GetParam();
ov_core_t* core = nullptr; ov_core_t* core = nullptr;
OV_EXPECT_OK(ov_core_create(&core)); OV_EXPECT_OK(ov_core_create(&core));
EXPECT_NE(nullptr, core); EXPECT_NE(nullptr, core);
const char* key = ov_property_key_enable_profiling; std::map<const char*, const char*> properties = {{ov_property_key_force_tbb_terminate, "YES"},
const char* enable = "YES"; {ov_property_key_enable_mmap, "NO"}};
OV_EXPECT_OK(ov_core_set_property(core, device_name.c_str(), key, enable));
for (const auto& property : properties) {
OV_EXPECT_OK(ov_core_set_property(core, "", property.first, property.second));
char* ret = nullptr; char* ret = nullptr;
OV_EXPECT_OK(ov_core_get_property(core, device_name.c_str(), key, &ret)); OV_EXPECT_OK(ov_core_get_property(core, "", property.first, &ret));
EXPECT_STREQ(enable, ret); EXPECT_STREQ(property.second, ret);
ov_free(ret); ov_free(ret);
}
ov_core_free(core); ov_core_free(core);
} }

View File

@ -30,6 +30,7 @@ void regmodule_properties(py::module m) {
wrap_property_RW(m_properties, ov::compilation_num_threads, "compilation_num_threads"); wrap_property_RW(m_properties, ov::compilation_num_threads, "compilation_num_threads");
wrap_property_RW(m_properties, ov::affinity, "affinity"); wrap_property_RW(m_properties, ov::affinity, "affinity");
wrap_property_RW(m_properties, ov::force_tbb_terminate, "force_tbb_terminate"); wrap_property_RW(m_properties, ov::force_tbb_terminate, "force_tbb_terminate");
wrap_property_RW(m_properties, ov::enable_mmap, "enable_mmap");
wrap_property_RO(m_properties, ov::supported_properties, "supported_properties"); wrap_property_RO(m_properties, ov::supported_properties, "supported_properties");
wrap_property_RO(m_properties, ov::available_devices, "available_devices"); wrap_property_RO(m_properties, ov::available_devices, "available_devices");

View File

@ -213,7 +213,8 @@ def test_properties_ro(ov_property_ro, expected_value):
"AFFINITY", "AFFINITY",
((properties.Affinity.NONE, properties.Affinity.NONE),), ((properties.Affinity.NONE, properties.Affinity.NONE),),
), ),
(properties.force_tbb_terminate, "FORCE_TBB_TERMINATE", ((True, True),)), (properties.force_tbb_terminate, "FORCE_TBB_TERMINATE", ((True, True), (False, False))),
(properties.enable_mmap, "ENABLE_MMAP", ((True, True), (False, False))),
(properties.hint.inference_precision, "INFERENCE_PRECISION_HINT", ((Type.f32, Type.f32),)), (properties.hint.inference_precision, "INFERENCE_PRECISION_HINT", ((Type.f32, Type.f32),)),
( (
properties.hint.model_priority, properties.hint.model_priority,

View File

@ -183,8 +183,7 @@ InputModel::Ptr FrontEnd::load_impl(const std::vector<ov::Any>& variants) const
weights = variant.as<std::shared_ptr<ngraph::runtime::AlignedBuffer>>(); weights = variant.as<std::shared_ptr<ngraph::runtime::AlignedBuffer>>();
} }
} }
bool use_map_allocator = bool enable_mmap = variants[variants.size() - 1].is<bool>() ? variants[variants.size() - 1].as<bool>() : false;
variants[variants.size() - 1].is<bool>() ? variants[variants.size() - 1].as<bool>() : false;
// Find weights if only path to xml was provided // Find weights if only path to xml was provided
if (weights_path.empty()) { if (weights_path.empty()) {
@ -202,7 +201,7 @@ InputModel::Ptr FrontEnd::load_impl(const std::vector<ov::Any>& variants) const
} }
} }
if (!weights_path.empty()) { if (!weights_path.empty()) {
if (use_map_allocator) if (enable_mmap)
weights = ov::load_mmap_object(weights_path); weights = ov::load_mmap_object(weights_path);
else { else {
std::ifstream bin_stream; std::ifstream bin_stream;

View File

@ -16,6 +16,15 @@ protected:
} }
}; };
class IRFrontendMMapTests : public ::testing::TestWithParam<bool>, public IRFrontendTestsImpl {
protected:
void SetUp() override {}
void TearDown() override {
RemoveTemporalFiles();
}
};
TEST_F(IRFrontendTests, elementary_model_reading_v11) { TEST_F(IRFrontendTests, elementary_model_reading_v11) {
std::string testModelV11 = R"V0G0N( std::string testModelV11 = R"V0G0N(
<net name="Network" version="11"> <net name="Network" version="11">
@ -241,7 +250,7 @@ TEST_F(IRFrontendTests, model_with_missing_weights) {
ASSERT_THROW(core.read_model(testModelV11, ov::Tensor()), ov::Exception); ASSERT_THROW(core.read_model(testModelV11, ov::Tensor()), ov::Exception);
} }
TEST_F(IRFrontendTests, model_with_weights_reading_from_disk) { TEST_P(IRFrontendMMapTests, model_with_weights_reading_from_disk) {
std::string xmlModel = R"V0G0N( std::string xmlModel = R"V0G0N(
<?xml version="1.0" ?> <?xml version="1.0" ?>
<net name="Network" version="11"> <net name="Network" version="11">
@ -316,7 +325,9 @@ TEST_F(IRFrontendTests, model_with_weights_reading_from_disk) {
std::shared_ptr<ov::Model> model; std::shared_ptr<ov::Model> model;
ASSERT_NO_THROW(model = core.read_model(xmlFileName, binFileName)); ov::Core new_core;
new_core.set_property(ov::enable_mmap(GetParam()));
ASSERT_NO_THROW(model = new_core.read_model(xmlFileName, binFileName));
ASSERT_TRUE(!!model); ASSERT_TRUE(!!model);
std::shared_ptr<ov::Model> modelRef; std::shared_ptr<ov::Model> modelRef;
@ -343,6 +354,8 @@ TEST_F(IRFrontendTests, model_with_weights_reading_from_disk) {
EXPECT_TRUE(res.valid) << res.message; EXPECT_TRUE(res.valid) << res.message;
} }
INSTANTIATE_TEST_SUITE_P(EnableMMapPropery, IRFrontendMMapTests, ::testing::Bool());
TEST_F(IRFrontendTests, model_without_weights_reading_from_disk) { TEST_F(IRFrontendTests, model_without_weights_reading_from_disk) {
std::string xmlModel = R"V0G0N( std::string xmlModel = R"V0G0N(
<?xml version="1.0" ?> <?xml version="1.0" ?>

View File

@ -678,6 +678,17 @@ static constexpr Property<std::tuple<unsigned int, unsigned int, unsigned int>,
*/ */
static constexpr Property<bool, PropertyMutability::RW> force_tbb_terminate{"FORCE_TBB_TERMINATE"}; static constexpr Property<bool, PropertyMutability::RW> force_tbb_terminate{"FORCE_TBB_TERMINATE"};
/**
* @brief Read-write property to configure `mmap()` use for model read. Enabled by default.
* For the moment only IR Frontend supports the property.
*
* value type: boolean
* - True enable `mmap()` use and map model
* - False disable `mmap()` use and read model
* @ingroup ov_runtime_cpp_prop_api
*/
static constexpr Property<bool, PropertyMutability::RW> enable_mmap{"ENABLE_MMAP"};
/** /**
* @brief Namespace with device properties * @brief Namespace with device properties
*/ */

View File

@ -924,6 +924,9 @@ ov::Any ov::CoreImpl::get_property_for_core(const std::string& name) const {
} else if (name == ov::hint::allow_auto_batching.name()) { } else if (name == ov::hint::allow_auto_batching.name()) {
const auto flag = coreConfig.get_allow_auto_batch(); const auto flag = coreConfig.get_allow_auto_batch();
return decltype(ov::hint::allow_auto_batching)::value_type(flag); return decltype(ov::hint::allow_auto_batching)::value_type(flag);
} else if (name == ov::enable_mmap.name()) {
const auto flag = coreConfig.get_enable_mmap();
return decltype(ov::enable_mmap)::value_type(flag);
} }
OPENVINO_THROW("Exception is thrown while trying to call get_property with unsupported property: '", name, "'"); OPENVINO_THROW("Exception is thrown while trying to call get_property with unsupported property: '", name, "'");
@ -1298,6 +1301,13 @@ void ov::CoreImpl::CoreConfig::set_and_update(ov::AnyMap& config) {
_flag_allow_auto_batching = flag; _flag_allow_auto_batching = flag;
config.erase(it); config.erase(it);
} }
it = config.find(ov::enable_mmap.name());
if (it != config.end()) {
auto flag = it->second.as<bool>();
_flag_enable_mmap = flag;
config.erase(it);
}
} }
void ov::CoreImpl::CoreConfig::set_cache_dir_for_device(const std::string& dir, const std::string& name) { void ov::CoreImpl::CoreConfig::set_cache_dir_for_device(const std::string& dir, const std::string& name) {
@ -1314,6 +1324,10 @@ bool ov::CoreImpl::CoreConfig::get_allow_auto_batch() const {
return _flag_allow_auto_batching; return _flag_allow_auto_batching;
} }
bool ov::CoreImpl::CoreConfig::get_enable_mmap() const {
return _flag_enable_mmap;
}
// Creating thread-safe copy of config including shared_ptr to ICacheManager // Creating thread-safe copy of config including shared_ptr to ICacheManager
// Passing empty or not-existing name will return global cache config // Passing empty or not-existing name will return global cache config
ov::CoreImpl::CoreConfig::CacheConfig ov::CoreImpl::CoreConfig::get_cache_config_for_device( ov::CoreImpl::CoreConfig::CacheConfig ov::CoreImpl::CoreConfig::get_cache_config_for_device(

View File

@ -85,6 +85,8 @@ private:
bool get_allow_auto_batch() const; bool get_allow_auto_batch() const;
bool get_enable_mmap() const;
// Creating thread-safe copy of config including shared_ptr to ICacheManager // Creating thread-safe copy of config including shared_ptr to ICacheManager
// Passing empty or not-existing name will return global cache config // Passing empty or not-existing name will return global cache config
CacheConfig get_cache_config_for_device(const ov::Plugin& plugin, ov::AnyMap& parsedConfig) const; CacheConfig get_cache_config_for_device(const ov::Plugin& plugin, ov::AnyMap& parsedConfig) const;
@ -94,6 +96,7 @@ private:
CacheConfig _cacheConfig; CacheConfig _cacheConfig;
std::map<std::string, CacheConfig> _cacheConfigPerDevice; std::map<std::string, CacheConfig> _cacheConfigPerDevice;
bool _flag_allow_auto_batching = true; bool _flag_allow_auto_batching = true;
bool _flag_enable_mmap = true;
}; };
struct CacheContent { struct CacheContent {

View File

@ -49,7 +49,12 @@ InferenceEngine::RemoteContext::Ptr ov::CoreImpl::GetDefaultContext(const std::s
InferenceEngine::CNNNetwork ov::CoreImpl::ReadNetwork(const std::string& modelPath, const std::string& binPath) const { InferenceEngine::CNNNetwork ov::CoreImpl::ReadNetwork(const std::string& modelPath, const std::string& binPath) const {
OV_ITT_SCOPE(FIRST_INFERENCE, ov::itt::domains::IE_RT, "CoreImpl::ReadNetwork from file"); OV_ITT_SCOPE(FIRST_INFERENCE, ov::itt::domains::IE_RT, "CoreImpl::ReadNetwork from file");
return InferenceEngine::details::ReadNetwork(modelPath, binPath, extensions, ov_extensions, is_new_api()); return InferenceEngine::details::ReadNetwork(modelPath,
binPath,
extensions,
ov_extensions,
is_new_api(),
coreConfig.get_enable_mmap());
} }
InferenceEngine::CNNNetwork ov::CoreImpl::ReadNetwork(const std::string& model, InferenceEngine::CNNNetwork ov::CoreImpl::ReadNetwork(const std::string& model,

View File

@ -418,7 +418,8 @@ CNNNetwork details::ReadNetwork(const std::string& modelPath,
const std::string& binPath, const std::string& binPath,
const std::vector<IExtensionPtr>& exts, const std::vector<IExtensionPtr>& exts,
const std::vector<ov::Extension::Ptr>& ov_exts, const std::vector<ov::Extension::Ptr>& ov_exts,
bool newAPI) { bool newAPI,
bool enable_mmap) {
#ifdef ENABLE_IR_V7_READER #ifdef ENABLE_IR_V7_READER
// IR v7 obsolete code // IR v7 obsolete code
{ {
@ -457,7 +458,7 @@ CNNNetwork details::ReadNetwork(const std::string& modelPath,
#endif #endif
params.emplace_back(weights_path); params.emplace_back(weights_path);
} }
params.emplace_back(/*use_ir_frontend_map_allocator=*/true); params.emplace_back(enable_mmap);
FE = manager.load_by_model(params); FE = manager.load_by_model(params);
if (FE) { if (FE) {

View File

@ -22,13 +22,15 @@ namespace details {
* @param exts vector with extensions * @param exts vector with extensions
* @param ov_exts vector with OpenVINO extensions * @param ov_exts vector with OpenVINO extensions
* @param newAPI Whether this function is called from OpenVINO 2.0 API * @param newAPI Whether this function is called from OpenVINO 2.0 API
* @param enable_mmap boolean to enable/disable `mmap` use in Frontend
* @return CNNNetwork * @return CNNNetwork
*/ */
CNNNetwork ReadNetwork(const std::string& modelPath, CNNNetwork ReadNetwork(const std::string& modelPath,
const std::string& binPath, const std::string& binPath,
const std::vector<IExtensionPtr>& exts, const std::vector<IExtensionPtr>& exts,
const std::vector<ov::Extension::Ptr>& ov_exts, const std::vector<ov::Extension::Ptr>& ov_exts,
bool newAPI); bool newAPI,
bool enable_mmap);
/** /**
* @brief Reads IR xml and bin (with the same name) files * @brief Reads IR xml and bin (with the same name) files
* @param model string with IR * @param model string with IR

View File

@ -689,10 +689,22 @@ TEST(OVClassBasicTest, SetTBBForceTerminatePropertyCoreNoThrow) {
bool value = true; bool value = true;
OV_ASSERT_NO_THROW(ie.set_property(ov::force_tbb_terminate(false))); OV_ASSERT_NO_THROW(ie.set_property(ov::force_tbb_terminate(false)));
OV_ASSERT_NO_THROW(value = ie.get_property(ov::force_tbb_terminate.name()).as<bool>()); OV_ASSERT_NO_THROW(value = ie.get_property(ov::force_tbb_terminate.name()).as<bool>());
EXPECT_EQ(value, false); EXPECT_FALSE(value);
OV_ASSERT_NO_THROW(ie.set_property(ov::force_tbb_terminate(true))); OV_ASSERT_NO_THROW(ie.set_property(ov::force_tbb_terminate(true)));
OV_ASSERT_NO_THROW(value = ie.get_property(ov::force_tbb_terminate.name()).as<bool>()); OV_ASSERT_NO_THROW(value = ie.get_property(ov::force_tbb_terminate.name()).as<bool>());
EXPECT_EQ(value, true); EXPECT_TRUE(value);
}
TEST(OVClassBasicTest, SetEnableMmapPropertyCoreNoThrow) {
ov::Core ie;
bool value = true;
OV_ASSERT_NO_THROW(ie.set_property(ov::enable_mmap(false)));
OV_ASSERT_NO_THROW(value = ie.get_property(ov::enable_mmap.name()).as<bool>());
EXPECT_FALSE(value);
OV_ASSERT_NO_THROW(ie.set_property(ov::enable_mmap(true)));
OV_ASSERT_NO_THROW(value = ie.get_property(ov::enable_mmap.name()).as<bool>());
EXPECT_TRUE(value);
} }
TEST(OVClassBasicTest, GetUnsupportedPropertyCoreThrow) { TEST(OVClassBasicTest, GetUnsupportedPropertyCoreThrow) {

View File

@ -338,6 +338,9 @@ std::vector<ov::AnyMap> OVPropertiesTestsWithComplieModelProps::getPropertiesVal
res.push_back({{ov::PropertyName(ov::force_tbb_terminate.name(), ov::force_tbb_terminate.mutability), true}}); res.push_back({{ov::PropertyName(ov::force_tbb_terminate.name(), ov::force_tbb_terminate.mutability), true}});
res.push_back({{ov::PropertyName(ov::force_tbb_terminate.name(), ov::force_tbb_terminate.mutability), false}}); res.push_back({{ov::PropertyName(ov::force_tbb_terminate.name(), ov::force_tbb_terminate.mutability), false}});
res.push_back({{ov::PropertyName(ov::enable_mmap.name(), ov::enable_mmap.mutability), true}});
res.push_back({{ov::PropertyName(ov::enable_mmap.name(), ov::enable_mmap.mutability), false}});
ov::streams::Num nums[] = {ov::streams::AUTO, ov::streams::NUMA}; ov::streams::Num nums[] = {ov::streams::AUTO, ov::streams::NUMA};
for (auto &num : nums) { for (auto &num : nums) {
res.push_back({{ov::PropertyName(ov::streams::num.name(), ov::streams::num.mutability), num}}); res.push_back({{ov::PropertyName(ov::streams::num.name(), ov::streams::num.mutability), num}});