OpenVINO Hybrid CPUs support internal interface (#4602)

* OpenVINO Hybrid CPUs support

* Remove custom::task_arena abstraction layout

* Get back to the custom::task_arena interface

* Add windows.h inclusion

* Fix typo in macro name

* Separate TBB and TBBbind packages

* Fix compile-time conditions

* Fix preprocessors conditions

* Fix typo

* Fix linking

* make linking private

* Fix typo

* Fix target_compile_definitions syntax

* Implement CMake install logic, update sha hash for the tbbbind_2_4 package

* Add tbbbind_2_4 required paths to setup_vars

* Update CI paths

* Include ie_parallel.hpp to ie_system_conf.cpp

* Try to update dependencies scripts

* Try to fix dependencies.bat

* Modify dependencies script

* Use static tbbbind_2_4 library

* Remove redundant paths from CI

* Update tbbbind package version

* Make custom::task_arena inherited from tbb::task_arena

* Incapsulate all TBB versions related logic inside the custom namespace

* Move custom layer header to internal scope + minor improvements

* Introduce new ThreadBindingType + fix compilation

* Fix compilation

* Use public tbbbind_2_4 package

* Apply review comments

* Fix compilation without tbbbind_2_4

* Fix compilation with different TBB versions

Co-authored-by: Kochin, Ivan <ivan.kochin@intel.com>
This commit is contained in:
Ivan Kochin
2021-04-22 18:11:13 +03:00
committed by GitHub
co-authored by Kochin, Ivan <ivan.kochin@intel.com>
parent e4d4eda31b
commit 636736825c
12 changed files with 446 additions and 26 deletions
+11
View File
@@ -145,6 +145,11 @@ if (THREADING STREQUAL "TBB" OR THREADING STREQUAL "TBB_AUTO")
TARGET_PATH "${TEMP}/tbb"
ENVIRONMENT "TBBROOT"
SHA256 "f1c9b9e2861efdaa01552bd25312ccbc5feeb45551e5f91ae61e29221c5c1479")
RESOLVE_DEPENDENCY(TBBBIND_2_4
ARCHIVE_WIN "tbbbind_2_4_static_win.zip"
TARGET_PATH "${TEMP}/tbbbind_2_4"
ENVIRONMENT "TBBBIND_2_4_ROOT"
SHA256 "1a3a05082cc5ef1a764d635793be347b82c795f0e9ced771515fc3706a4dc4f0")
elseif(ANDROID) # Should be before LINUX due LINUX is detected as well
RESOLVE_DEPENDENCY(TBB
ARCHIVE_ANDROID "tbb2020_20200404_android.tgz"
@@ -156,6 +161,10 @@ if (THREADING STREQUAL "TBB" OR THREADING STREQUAL "TBB_AUTO")
ARCHIVE_LIN "tbb2020_20200415_lin_strip.tgz"
TARGET_PATH "${TEMP}/tbb"
SHA256 "95b2f3b0b70c7376a0c7de351a355c2c514b42c4966e77e3e34271a599501008")
RESOLVE_DEPENDENCY(TBBBIND_2_4
ARCHIVE_LIN "tbbbind_2_4_static_lin.tgz"
TARGET_PATH "${TEMP}/tbbbind_2_4"
SHA256 "888582a94f81821f9894cc089db36d5a6c2e0b6998cfa1fec0c027f28c597ada")
elseif(LINUX AND AARCH64)
RESOLVE_DEPENDENCY(TBB
ARCHIVE_LIN "keembay/tbb2020_38404_kmb_lic.tgz"
@@ -175,6 +184,8 @@ if (THREADING STREQUAL "TBB" OR THREADING STREQUAL "TBB_AUTO")
update_deps_cache(TBBROOT "${TBB}" "Path to TBB root folder")
update_deps_cache(TBB_DIR "${TBB}/cmake" "Path to TBB cmake folder")
update_deps_cache(TBBBIND_2_4_DIR "${TBBBIND_2_4}/cmake" "Path to TBBBIND_2_4 cmake folder")
if (WIN32)
log_rpath_from_dir(TBB "${TBB}/bin")
else ()
+1 -7
View File
@@ -8,13 +8,7 @@ function(set_ie_threading_interface_for TARGET_NAME)
set("TBB_FOUND" ${TBB_FOUND} PARENT_SCOPE)
set("TBB_IMPORTED_TARGETS" ${TBB_IMPORTED_TARGETS} PARENT_SCOPE)
set("TBB_VERSION" ${TBB_VERSION} PARENT_SCOPE)
if (TBB_FOUND)
if (TBB_VERSION VERSION_LESS 2020)
ext_message(WARNING "TBB version is less than OpenVINO recommends to use.\
Some TBB related features like NUMA-aware tbb::task_arena\
execution will be disabled.")
endif()
else ()
if (NOT TBB_FOUND)
ext_message(WARNING "TBB was not found by the configured TBB_DIR/TBBROOT path.\
SEQ method will be used.")
endif ()
+4
View File
@@ -32,6 +32,10 @@
#ifndef TBB_PREVIEW_NUMA_SUPPORT
# define TBB_PREVIEW_NUMA_SUPPORT 1
#endif
#ifndef TBB_PREVIEW_TASK_ARENA_CONSTRAINTS_EXTENSION
# define TBB_PREVIEW_TASK_ARENA_CONSTRAINTS_EXTENSION 1
#endif
#include "tbb/blocked_range.h"
#include "tbb/blocked_range2d.h"
#include "tbb/blocked_range3d.h"
@@ -214,6 +214,7 @@ DECLARE_CONFIG_KEY(CPU_THREADS_NUM);
*/
DECLARE_CONFIG_KEY(CPU_BIND_THREAD);
DECLARE_CONFIG_VALUE(NUMA);
DECLARE_CONFIG_VALUE(HYBRID_AWARE);
/**
* @brief Optimize CPU execution to maximize throughput.
@@ -4,6 +4,10 @@
set (TARGET_NAME "inference_engine")
if(THREADING STREQUAL "TBB" OR THREADING STREQUAL "TBB_AUTO")
find_package(TBBBIND_2_4)
endif()
file (GLOB LIBRARY_SRC
${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
${CMAKE_CURRENT_SOURCE_DIR}/cpp/*.cpp
@@ -121,6 +125,10 @@ target_include_directories(${TARGET_NAME}_obj PRIVATE "${CMAKE_CURRENT_SOURCE_DI
target_link_libraries(${TARGET_NAME}_obj PRIVATE ${TARGET_NAME}_reader_api)
set_ie_threading_interface_for(${TARGET_NAME}_obj)
if (TBBBIND_2_4_FOUND)
target_compile_definitions(${TARGET_NAME}_obj PRIVATE -DTBBBIND_2_4_AVAILABLE)
target_link_libraries(${TARGET_NAME}_obj PRIVATE ${TBBBIND_2_4_IMPORTED_TARGETS})
endif()
add_cpplint_target(${TARGET_NAME}_cpplint FOR_TARGETS ${TARGET_NAME}_obj)
@@ -136,6 +144,10 @@ ie_add_vs_version_file(NAME ${TARGET_NAME}
FILEDESCRIPTION "Inference Engine Core Runtime library")
set_ie_threading_interface_for(${TARGET_NAME})
if (TBBBIND_2_4_FOUND)
target_compile_definitions(${TARGET_NAME} PRIVATE -DTBBBIND_2_4_AVAILABLE)
target_link_libraries(${TARGET_NAME} PRIVATE ${TBBBIND_2_4_IMPORTED_TARGETS})
endif()
target_link_libraries(${TARGET_NAME} PRIVATE pugixml openvino::itt ${CMAKE_DL_LIBS} Threads::Threads
${NGRAPH_LIBRARIES} inference_engine_transformations)
@@ -163,6 +175,10 @@ add_library(${TARGET_NAME}_s STATIC
${IE_STATIC_DEPENDENT_FILES})
set_ie_threading_interface_for(${TARGET_NAME}_s)
if (TBBBIND_2_4_FOUND)
target_compile_definitions(${TARGET_NAME}_s PRIVATE -DTBBBIND_2_4_AVAILABLE)
target_link_libraries(${TARGET_NAME}_s PRIVATE ${TBBBIND_2_4_IMPORTED_TARGETS})
endif()
target_include_directories(${TARGET_NAME}_s PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}"
$<TARGET_PROPERTY:inference_engine_plugin_api,INTERFACE_INCLUDE_DIRECTORIES>
@@ -4,7 +4,7 @@
#include <cstdlib>
#include <cstring>
#include "ie_parallel.hpp"
#include "threading/ie_parallel_custom_arena.hpp"
#include "ie_system_conf.h"
#include <iostream>
#include <vector>
@@ -98,11 +98,7 @@ std::vector<int> getAvailableNUMANodes() { return {0}; }
#if ((IE_THREAD == IE_THREAD_TBB) || (IE_THREAD == IE_THREAD_TBB_AUTO))
std::vector<int> getAvailableNUMANodes() {
#if TBB_INTERFACE_VERSION >= 11100
return tbb::info::numa_nodes();
#else
return {0};
#endif
return custom::info::numa_nodes();
}
#endif
@@ -15,7 +15,7 @@
#include <utility>
#include "threading/ie_thread_local.hpp"
#include "ie_parallel.hpp"
#include "ie_parallel_custom_arena.hpp"
#include "ie_system_conf.h"
#include "threading/ie_thread_affinity.hpp"
#include "threading/ie_cpu_streams_executor.hpp"
@@ -71,15 +71,21 @@ struct CPUStreamsExecutor::Impl {
((_impl->_config._streams + _impl->_usedNumaNodes.size() - 1)/_impl->_usedNumaNodes.size()))
: _impl->_usedNumaNodes.at(_streamId % _impl->_usedNumaNodes.size());
#if IE_THREAD == IE_THREAD_TBB || IE_THREAD == IE_THREAD_TBB_AUTO
auto concurrency = (0 == _impl->_config._threadsPerStream) ? tbb::task_arena::automatic : _impl->_config._threadsPerStream;
if (ThreadBindingType::NUMA == _impl->_config._threadBindingType) {
#if TBB_INTERFACE_VERSION >= 11100 // TBB has numa aware task_arena api
_taskArena.reset(new tbb::task_arena{tbb::task_arena::constraints{_numaNodeId, concurrency}});
#else
_taskArena.reset(new tbb::task_arena{concurrency});
#endif
auto concurrency = (0 == _impl->_config._threadsPerStream) ? custom::task_arena::automatic : _impl->_config._threadsPerStream;
if (ThreadBindingType::HYBRID_AWARE == _impl->_config._threadBindingType) {
_taskArena.reset(new custom::task_arena{
custom::task_arena::constraints{}
.set_core_type(custom::info::core_types().back())
.set_max_concurrency(concurrency)
});
} else if (ThreadBindingType::NUMA == _impl->_config._threadBindingType) {
_taskArena.reset(new custom::task_arena{
custom::task_arena::constraints{}
.set_numa_id(_numaNodeId)
.set_max_concurrency(concurrency)
});
} else if ((0 != _impl->_config._threadsPerStream) || (ThreadBindingType::CORES == _impl->_config._threadBindingType)) {
_taskArena.reset(new tbb::task_arena{concurrency});
_taskArena.reset(new custom::task_arena{concurrency});
if (ThreadBindingType::CORES == _impl->_config._threadBindingType) {
CpuSet processMask;
int ncpus = 0;
@@ -140,7 +146,7 @@ struct CPUStreamsExecutor::Impl {
bool _execute = false;
std::queue<Task> _taskQueue;
#if IE_THREAD == IE_THREAD_TBB || IE_THREAD == IE_THREAD_TBB_AUTO
std::unique_ptr<tbb::task_arena> _taskArena;
std::unique_ptr<custom::task_arena> _taskArena;
std::unique_ptr<Observer> _observer;
#endif
};
@@ -122,6 +122,9 @@ Parameter IStreamsExecutor::Config::GetConfig(const std::string& key) {
case IStreamsExecutor::ThreadBindingType::NUMA:
return {CONFIG_VALUE(NUMA)};
break;
case IStreamsExecutor::ThreadBindingType::HYBRID_AWARE:
return {CONFIG_VALUE(HYBRID_AWARE)};
break;
}
} else if (key == CONFIG_KEY(CPU_THROUGHPUT_STREAMS)) {
return {_streams};
@@ -0,0 +1,281 @@
// Copyright (C) 2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "ie_parallel_custom_arena.hpp"
#if IE_THREAD == IE_THREAD_TBB || IE_THREAD == IE_THREAD_TBB_AUTO
#ifndef TBBBIND_2_4_AVAILABLE
# define TBBBIND_2_4_AVAILABLE 0
#endif
#define USE_TBBBIND_2_4 (TBBBIND_2_4_AVAILABLE && TBB_INTERFACE_VERSION < 12020)
#define TBB_NUMA_SUPPORT_PRESENT (TBB_INTERFACE_VERSION >= 11100)
#define TBB_HYBRID_CPUS_SUPPORT_PRESENT (TBB_INTERFACE_VERSION >= 12020)
#if defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#endif
namespace custom {
namespace detail {
#if USE_TBBBIND_2_4
class binding_handler;
extern "C" {
void __TBB_internal_initialize_system_topology(
std::size_t groups_num,
int& numa_nodes_count, int*& numa_indexes_list,
int& core_types_count, int*& core_types_indexes_list
);
binding_handler* __TBB_internal_allocate_binding_handler(int number_of_slots, int numa_id, int core_type_id, int max_threads_per_core);
void __TBB_internal_deallocate_binding_handler(binding_handler* handler_ptr);
void __TBB_internal_apply_affinity(binding_handler* handler_ptr, int slot_num);
void __TBB_internal_restore_affinity(binding_handler* handler_ptr, int slot_num);
int __TBB_internal_get_default_concurrency(int numa_id, int core_type_id, int max_threads_per_core);
}
int get_processors_group_num() {
#if defined(_WIN32) || defined(_WIN64)
SYSTEM_INFO si;
GetNativeSystemInfo(&si);
DWORD_PTR pam, sam, m = 1;
GetProcessAffinityMask(GetCurrentProcess(), &pam, &sam);
int nproc = 0;
for (std::size_t i = 0; i < sizeof(DWORD_PTR) * CHAR_BIT; ++i, m <<= 1) {
if ( pam & m )
++nproc;
}
if (nproc == static_cast<int>(si.dwNumberOfProcessors)) {
return GetActiveProcessorGroupCount();
}
#endif
return 1;
}
bool is_binding_environment_valid() {
#if defined(_WIN32) && !defined(_WIN64)
static bool result = [] {
// For 32-bit Windows applications, process affinity masks can only support up to 32 logical CPUs.
SYSTEM_INFO si;
GetNativeSystemInfo(&si);
if (si.dwNumberOfProcessors > 32) return false;
return true;
}();
return result;
#else
return true;
#endif /* _WIN32 && !_WIN64 */
}
static int numa_nodes_count = 0;
static int* numa_nodes_indexes = nullptr;
static int core_types_count = 0;
static int* core_types_indexes = nullptr;
void initialize_system_topology() {
static std::once_flag is_topology_initialized;
std::call_once(is_topology_initialized, [&]{
if (is_binding_environment_valid()) {
__TBB_internal_initialize_system_topology(
get_processors_group_num(),
numa_nodes_count, numa_nodes_indexes,
core_types_count, core_types_indexes);
} else {
static int dummy_index = task_arena::automatic;
numa_nodes_count = 1;
numa_nodes_indexes = &dummy_index;
core_types_count = 1;
core_types_indexes = &dummy_index;
}
});
}
class binding_observer : public tbb::task_scheduler_observer {
binding_handler* my_binding_handler;
public:
binding_observer(tbb::task_arena& ta, int num_slots, const constraints& c)
: task_scheduler_observer(ta) {
detail::initialize_system_topology();
my_binding_handler = detail::__TBB_internal_allocate_binding_handler(num_slots, c.numa_id, c.core_type, c.max_threads_per_core);
}
~binding_observer() {
detail::__TBB_internal_deallocate_binding_handler(my_binding_handler);
}
void on_scheduler_entry(bool) override {
detail::__TBB_internal_apply_affinity(my_binding_handler, tbb::this_task_arena::current_thread_index());
}
void on_scheduler_exit(bool) override {
detail::__TBB_internal_restore_affinity(my_binding_handler, tbb::this_task_arena::current_thread_index());
}
};
binding_observer* construct_binding_observer(tbb::task_arena& ta, int num_slots, const constraints& c) {
binding_observer* observer = nullptr;
if (detail::is_binding_environment_valid() &&
((c.core_type >= 0 && info::core_types().size() > 1) || (c.numa_id >= 0 && info::numa_nodes().size() > 1) || c.max_threads_per_core > 0)) {
observer = new binding_observer(ta, num_slots, c);
observer->observe(true);
}
return observer;
}
void destroy_binding_observer(binding_observer* observer) {
observer->observe(false);
delete observer;
}
#endif /*USE_TBBBIND_2_4*/
#if TBB_NUMA_SUPPORT_PRESENT
tbb::task_arena::constraints convert_constraints(custom::task_arena::constraints& c) {
tbb::task_arena::constraints result{};
#if TBB_HYBRID_CPUS_SUPPORT_PRESENT
result.core_type = c.core_type;
result.max_threads_per_core = c.max_threads_per_core;
#endif
result.numa_id = c.numa_id;
result.max_concurrency = c.max_concurrency;
return result;
}
#endif
} // namespace detail
task_arena::task_arena(int max_concurrency_, unsigned reserved_for_masters)
: tbb::task_arena{max_concurrency_, reserved_for_masters}
, my_initialization_state{}
, my_constraints{}
, my_binding_observer{nullptr}
{}
task_arena::task_arena(const constraints& constraints_, unsigned reserved_for_masters)
: tbb::task_arena{info::default_concurrency(constraints_), reserved_for_masters}
, my_initialization_state{}
, my_constraints{constraints_}
, my_binding_observer{nullptr}
{}
task_arena::task_arena(const task_arena &s)
: tbb::task_arena{s}
, my_initialization_state{}
, my_constraints{s.my_constraints}
, my_binding_observer{nullptr}
{}
void task_arena::initialize() {
#if USE_TBBBIND_2_4
std::call_once(my_initialization_state, [this] {
tbb::task_arena::initialize();
my_binding_observer = detail::construct_binding_observer(
*this, tbb::task_arena::max_concurrency(), my_constraints);
});
#elif TBB_NUMA_SUPPORT_PRESENT || TBB_HYBRID_CPUS_SUPPORT_PRESENT
tbb::task_arena::initialize(convert_constraints(my_constraints));
#else
tbb::task_arena::initialize();
#endif
}
void task_arena::initialize(int max_concurrency_, unsigned reserved_for_masters) {
#if USE_TBBBIND_2_4
std::call_once(my_initialization_state, [this, &max_concurrency_, &reserved_for_masters] {
tbb::task_arena::initialize(max_concurrency_, reserved_for_masters);
my_binding_observer = detail::construct_binding_observer(
*this, tbb::task_arena::max_concurrency(), my_constraints);
});
#elif TBB_NUMA_SUPPORT_PRESENT || TBB_HYBRID_CPUS_SUPPORT_PRESENT
my_constraints.max_concurrency = max_concurrency_;
tbb::task_arena::initialize(convert_constraints(my_constraints), reserved_for_masters);
#else
tbb::task_arena::initialize(max_concurrency_, reserved_for_masters);
#endif
}
void task_arena::initialize(constraints constraints_, unsigned reserved_for_masters) {
std::call_once(my_initialization_state, [this, &constraints_, &reserved_for_masters] {
my_constraints = constraints_;
#if USE_TBBBIND_2_4
tbb::task_arena::initialize(info::default_concurrency(constraints_), reserved_for_masters);
my_binding_observer = detail::construct_binding_observer(
*this, tbb::task_arena::max_concurrency(), my_constraints);
#elif TBB_NUMA_SUPPORT_PRESENT || TBB_HYBRID_CPUS_SUPPORT_PRESENT
tbb::task_arena::initialize(convert_constraints(my_constraints), reserved_for_masters);
#else
tbb::task_arena::initialize(my_constraints.max_concurrency, reserved_for_masters);
#endif
});
}
int task_arena::max_concurrency() {
initialize();
return tbb::task_arena::max_concurrency();
}
task_arena::~task_arena() {
#if USE_TBBBIND_2_4
if (my_binding_observer != nullptr) {
detail::destroy_binding_observer(my_binding_observer);
}
#endif
}
namespace info {
std::vector<numa_node_id> numa_nodes() {
#if USE_TBBBIND_2_4
detail::initialize_system_topology();
std::vector<numa_node_id> node_indexes(detail::numa_nodes_count);
std::memcpy(node_indexes.data(), detail::numa_nodes_indexes, detail::numa_nodes_count * sizeof(int));
return node_indexes;
#elif TBB_NUMA_SUPPORT_PRESENT
return tbb::info::numa_nodes();
#else
return {tbb::task_arena::automatic};
#endif
}
std::vector<core_type_id> core_types() {
#if USE_TBBBIND_2_4
detail::initialize_system_topology();
std::vector<numa_node_id> core_type_indexes(detail::core_types_count);
std::memcpy(core_type_indexes.data(), detail::core_types_indexes, detail::core_types_count * sizeof(int));
return core_type_indexes;
#elif TBB_HYBRID_CPUS_SUPPORT_PRESENT
return tbb::info::core_types();
#else
return {tbb::task_arena::automatic};
#endif
}
int default_concurrency(task_arena::constraints c) {
if (c.max_concurrency > 0) {
return c.max_concurrency;
}
#if USE_TBBBIND_2_4
if (detail::is_binding_environment_valid()) {
detail::initialize_system_topology();
return detail::__TBB_internal_get_default_concurrency(c.numa_id, c.core_type, c.max_threads_per_core);
}
return tbb::this_task_arena::max_concurrency();
#elif TBB_HYBRID_CPUS_SUPPORT_PRESENT
return tbb::info::default_concurrency(convert_constraints(c));
#elif TBB_NUMA_SUPPORT_PRESENT
return tbb::info::default_concurrency(c.numa_id);
#else
return tbb::this_task_arena::max_concurrency();
#endif
}
int default_concurrency(numa_node_id id) {
return default_concurrency(task_arena::constraints{}.set_numa_id(id));
}
} // namespace info
} // namespace custom
#endif /*IE_THREAD == IE_THREAD_TBB || IE_THREAD == IE_THREAD_TBB_AUTO*/
@@ -0,0 +1,103 @@
// Copyright (C) 2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
/**
* @brief Contains declarations and custom threading interfaces based on TBB info and task_arena APIs.
*
* @file ie_parallel_custom.hpp
*/
#pragma once
#include "ie_parallel.hpp"
#if (IE_THREAD == IE_THREAD_TBB || IE_THREAD == IE_THREAD_TBB_AUTO)
#include <cstddef>
#include <type_traits>
#include <mutex>
#include <vector>
namespace custom {
using numa_node_id = int;
using core_type_id = int;
namespace detail {
struct constraints {
constraints(numa_node_id id = -1, int maximal_concurrency = -1)
: numa_id{id}
, max_concurrency{maximal_concurrency}
, core_type{tbb::task_arena::automatic}
, max_threads_per_core{tbb::task_arena::automatic}
{}
constraints& set_numa_id(numa_node_id id) {
numa_id = id;
return *this;
}
constraints& set_max_concurrency(int maximal_concurrency) {
max_concurrency = maximal_concurrency;
return *this;
}
constraints& set_core_type(core_type_id id) {
core_type = id;
return *this;
}
constraints& set_max_threads_per_core(int threads_number) {
max_threads_per_core = threads_number;
return *this;
}
numa_node_id numa_id = tbb::task_arena::automatic;
int max_concurrency = tbb::task_arena::automatic;
core_type_id core_type = tbb::task_arena::automatic;
int max_threads_per_core = tbb::task_arena::automatic;
};
class binding_observer;
} // namespace detail
class task_arena : public tbb::task_arena {
std::once_flag my_initialization_state;
detail::constraints my_constraints;
detail::binding_observer* my_binding_observer;
public:
using constraints = detail::constraints;
static const int automatic = tbb::task_arena::automatic;
task_arena(int max_concurrency_ = automatic, unsigned reserved_for_masters = 1);
task_arena(const constraints& constraints_, unsigned reserved_for_masters = 1);
task_arena(const task_arena &s);
void initialize();
void initialize(int max_concurrency_, unsigned reserved_for_masters = 1);
void initialize(constraints constraints_, unsigned reserved_for_masters = 1);
int max_concurrency();
template<typename F>
void enqueue(F&& f) {
initialize();
tbb::task_arena::enqueue(std::forward<F>(f));
}
template<typename F>
auto execute(F&& f) -> decltype(f()) {
initialize();
return tbb::task_arena::execute(std::forward<F>(f));
}
~task_arena();
};
namespace info {
std::vector<numa_node_id> numa_nodes();
std::vector<core_type_id> core_types();
int default_concurrency(numa_node_id id = task_arena::automatic);
int default_concurrency(task_arena::constraints c);
} // namespace info
} // namespace custom
#endif /*(IE_THREAD == IE_THREAD_TBB || IE_THREAD == IE_THREAD_TBB_AUTO)*/
@@ -127,6 +127,9 @@ void Config::updateProperties() {
case IStreamsExecutor::ThreadBindingType::NUMA:
_config.insert({ PluginConfigParams::KEY_CPU_BIND_THREAD, PluginConfigParams::NUMA });
break;
case IStreamsExecutor::ThreadBindingType::HYBRID_AWARE:
_config.insert({ PluginConfigParams::KEY_CPU_BIND_THREAD, PluginConfigParams::HYBRID_AWARE});
break;
}
if (collectPerfCounters == true)
_config.insert({ PluginConfigParams::KEY_PERF_COUNT, PluginConfigParams::YES });
@@ -39,9 +39,11 @@ public:
* @brief Defines thread binding type
*/
enum ThreadBindingType : std::uint8_t {
NONE, //!< Don't bind threads
CORES, //!< Bind threads to cores
NUMA //!< Bind threads to NUMA nodes
NONE, //!< Don't bind the inference threads
CORES, //!< Bind inference threads to the CPU cores (round-robin)
// the following modes are implemented only for the TBB code-path:
NUMA, //!< Bind to the NUMA nodes (default mode for the non-hybrid CPUs on the Win/MacOS, where the 'CORES' is not implemeneted)
HYBRID_AWARE //!< Let the runtime bind the inference threads depending on the cores type (default mode for the hybrid CPUs)
};
/**