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:
co-authored by
Kochin, Ivan <ivan.kochin@intel.com>
parent
e4d4eda31b
commit
636736825c
@@ -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 ()
|
||||
|
||||
@@ -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 ()
|
||||
|
||||
@@ -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};
|
||||
|
||||
+281
@@ -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*/
|
||||
+103
@@ -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)
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user