Skip to content

Commit a5be820

Browse files
Update threading configuration for NVL and PTL (#36367)
### Details: - *Update threading configuration for NVL and PTL* 1. Improve hybrid CPU latency heuristics to enable more ALL/AUTO configurations on high LP E-core-share platforms. 2. Add new model-profile-based AUTO rules using lp_ecore_share, memory tolerance, convolution pressure, and GEMM ratio. 3. Refine latency stream sizing so model_prefer_threads is honored when building single-stream ALL core configurations. 4. Extend CPUStreamsExecutor internal stream metadata from a single core type to multiple core types. 5. Update task arena creation logic to bind streams by the actual set of eligible core types instead of forcing a single-type binding. 6. Add unit coverage for mixed-core stream metadata and stream type selection behavior. Dependency PR: [PR#36286](#36286) ### Tickets: - CVS-183947 - CVS-180761 ### Test data: Machine: 1.NVL windows from validation team (8Pcores+16Ecores+4LPEcores), 2.PTL X7 358H 32GB windows (4Pcores+8Ecores+4LPEcores) Models: 209 static models from WW05_static_2026.0.0-20947 The geomean of latency with PR vs master: NVL: 0.97583 PTL: 0.92095 The performance data for all models: <img width="285" height="188" alt="image" src="https://github.com/user-attachments/assets/d6046306-e68e-4a9a-8f3b-dfe616539805" /> The performance data for the models with **threads and partitioner changed in current PR**: <img width="284" height="165" alt="image" src="https://github.com/user-attachments/assets/e869d620-e743-4dd0-b649-b66ca6ffe713" /> --------- Co-authored-by: Chen Peter <peter.chen@intel.com>
1 parent b308ae2 commit a5be820

8 files changed

Lines changed: 600 additions & 122 deletions

File tree

src/inference/dev_api/openvino/runtime/threading/cpu_streams_executor_internal.hpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,18 @@ enum StreamCreateType {
3030
* @param[in] streams_info_table streams information table
3131
* @param[out] stream_type stream create type
3232
* @param[out] concurrency the number of threads created at the same time
33-
* @param[out] core_type core type
33+
* @param[out] core_types core types used for thread binding
3434
* @param[out] numa_node_id numa node id
35+
* @param[out] socket_id socket id
3536
* @param[out] max_threads_per_core the max number of threads per cpu core
3637
*/
3738
void get_cur_stream_info(const int stream_id,
3839
const bool cpu_pinning,
39-
const std::vector<std::vector<int>> org_proc_type_table,
40-
const std::vector<std::vector<int>> streams_info_table,
40+
const std::vector<std::vector<int>>& org_proc_type_table,
41+
const std::vector<std::vector<int>>& streams_info_table,
4142
StreamCreateType& stream_type,
4243
int& concurrency,
43-
int& core_type,
44+
std::vector<int>& core_types,
4445
int& numa_node_id,
4546
int& socket_id,
4647
int& max_threads_per_core);

src/inference/src/dev/threading/cpu_streams_executor.cpp

Lines changed: 67 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include "openvino/runtime/threading/cpu_streams_executor.hpp"
66

7+
#include <algorithm>
78
#include <atomic>
89
#include <condition_variable>
910
#include <memory>
@@ -99,22 +100,60 @@ struct CPUStreamsExecutor::Impl {
99100
}
100101

101102
#if OV_THREAD == OV_THREAD_TBB || OV_THREAD == OV_THREAD_TBB_AUTO || OV_THREAD == OV_THREAD_TBB_ADAPTIVE
103+
custom::core_type_id map_proc_kind_to_tbb_core_type(const std::vector<custom::core_type_id>& sys_core_types,
104+
const int proc_kind) {
105+
if (sys_core_types.empty()) {
106+
return custom::task_arena::automatic;
107+
}
108+
109+
switch (proc_kind) {
110+
case MAIN_CORE_PROC:
111+
case HYPER_THREADING_PROC:
112+
return sys_core_types.back();
113+
case EFFICIENT_CORE_PROC:
114+
return sys_core_types.size() >= 2 ? *(sys_core_types.end() - 2) : sys_core_types.back();
115+
case LP_EFFICIENT_CORE_PROC:
116+
return sys_core_types.front();
117+
default:
118+
return sys_core_types.back();
119+
}
120+
}
121+
122+
std::vector<custom::core_type_id> map_proc_kinds_to_tbb_core_types(
123+
const std::vector<custom::core_type_id>& sys_core_types,
124+
const std::vector<int>& proc_kinds) {
125+
std::vector<custom::core_type_id> mapped_core_types;
126+
mapped_core_types.reserve(proc_kinds.size());
127+
128+
for (const auto proc_kind : proc_kinds) {
129+
const auto core_type = map_proc_kind_to_tbb_core_type(sys_core_types, proc_kind);
130+
if (core_type != custom::task_arena::automatic &&
131+
std::find(mapped_core_types.begin(), mapped_core_types.end(), core_type) ==
132+
mapped_core_types.end()) {
133+
mapped_core_types.push_back(core_type);
134+
}
135+
}
136+
137+
return mapped_core_types;
138+
}
139+
102140
void create_tbb_task_arena(const int stream_id,
103141
const StreamCreateType stream_type,
104142
const int concurrency,
105-
const int core_type,
143+
const std::vector<int>& core_types,
106144
const int numa_node_id,
107145
const int socket_id,
108146
const int max_threads_per_core) {
109147
auto stream_processors = _impl->_config.get_stream_processor_ids();
110148
_numaNodeId = numa_node_id;
111149
_socketId = socket_id;
150+
auto _stream_type = stream_type;
112151
# if (TBB_INTERFACE_VERSION < 12000)
113152
const auto tbb_version = tbb::TBB_runtime_interface_version();
114153
# else
115154
const auto tbb_version = TBB_runtime_interface_version();
116155
# endif
117-
if (stream_type == STREAM_WITHOUT_PARAM) {
156+
if (_stream_type == STREAM_WITH_CORE_TYPE) {
118157
int version_major = tbb_version / 10;
119158
int version_patch = tbb_version % 10;
120159
bool support_core_types = false;
@@ -124,19 +163,17 @@ struct CPUStreamsExecutor::Impl {
124163
version_patch >= TBB_VERSION_PATCH_CORE_TYPES_LINUX)) {
125164
support_core_types = true;
126165
}
127-
const auto core_types = custom::info::core_types();
128-
if (support_core_types && core_types.size() >= MIN_CORE_TYPES_FOR_PTL) {
129-
_taskArena.reset(new custom::task_arena{
130-
custom::task_arena::constraints{}
131-
.set_max_concurrency(concurrency)
132-
.set_max_threads_per_core(max_threads_per_core)
133-
.set_core_types({core_types.end() - MIN_CORE_TYPES_FOR_PTL + 1, core_types.end()})});
166+
if (core_types.size() == 1 || (core_types.size() > 1 && support_core_types)) {
167+
_stream_type = STREAM_WITH_CORE_TYPE;
134168
} else {
135-
_taskArena.reset(new custom::task_arena{custom::task_arena::constraints{}
136-
.set_max_concurrency(concurrency)
137-
.set_max_threads_per_core(max_threads_per_core)});
169+
_stream_type = STREAM_WITHOUT_PARAM;
138170
}
139-
} else if (stream_type == STREAM_WITH_NUMA_ID) {
171+
}
172+
if (_stream_type == STREAM_WITHOUT_PARAM) {
173+
_taskArena.reset(new custom::task_arena{custom::task_arena::constraints{}
174+
.set_max_concurrency(concurrency)
175+
.set_max_threads_per_core(max_threads_per_core)});
176+
} else if (_stream_type == STREAM_WITH_NUMA_ID) {
140177
// Numa node id has used different mapping methods in TBBBind since oneTBB 2021.4.0
141178
# if USE_TBBBIND_2_5
142179
auto real_numa_node_id = _numaNodeId;
@@ -150,19 +187,21 @@ struct CPUStreamsExecutor::Impl {
150187
.set_numa_id(real_numa_node_id)
151188
.set_max_concurrency(concurrency)
152189
.set_max_threads_per_core(max_threads_per_core)});
153-
} else if (stream_type == STREAM_WITH_CORE_TYPE) {
154-
const auto core_types = custom::info::core_types();
155-
auto real_core_type = (core_type == MAIN_CORE_PROC || core_type == HYPER_THREADING_PROC)
156-
? core_types.back()
157-
: core_types.front();
158-
// core_types=[LPECore, Ecore, Pcore]
159-
if (core_type == EFFICIENT_CORE_PROC && core_types.size() >= MIN_CORE_TYPES_FOR_PTL) {
160-
real_core_type = *(core_types.end() - MIN_CORE_TYPES_FOR_PTL + 1);
190+
} else if (_stream_type == STREAM_WITH_CORE_TYPE) {
191+
// sys_core_types = [LPECore, Ecore, Pcore]
192+
const auto sys_core_types = custom::info::core_types();
193+
const auto mapped_core_types = map_proc_kinds_to_tbb_core_types(sys_core_types, core_types);
194+
auto constraints = custom::task_arena::constraints{}
195+
.set_max_concurrency(concurrency)
196+
.set_max_threads_per_core(max_threads_per_core);
197+
198+
if (mapped_core_types.empty()) {
199+
_taskArena.reset(new custom::task_arena{constraints});
200+
} else if (mapped_core_types.size() == 1) {
201+
_taskArena.reset(new custom::task_arena{constraints.set_core_type(mapped_core_types.front())});
202+
} else {
203+
_taskArena.reset(new custom::task_arena{constraints.set_core_types(mapped_core_types)});
161204
}
162-
_taskArena.reset(new custom::task_arena{custom::task_arena::constraints{}
163-
.set_core_type(real_core_type)
164-
.set_max_concurrency(concurrency)
165-
.set_max_threads_per_core(max_threads_per_core)});
166205
} else {
167206
_taskArena.reset(new custom::task_arena{concurrency});
168207
_cpu_ids =
@@ -180,7 +219,7 @@ struct CPUStreamsExecutor::Impl {
180219
}
181220
void init_stream() {
182221
int concurrency;
183-
int cpu_core_type;
222+
std::vector<int> cpu_core_types;
184223
int numa_node_id;
185224
int socket_id;
186225
int max_threads_per_core;
@@ -195,7 +234,7 @@ struct CPUStreamsExecutor::Impl {
195234
_impl->_config.get_streams_info_table(),
196235
stream_type,
197236
concurrency,
198-
cpu_core_type,
237+
cpu_core_types,
199238
numa_node_id,
200239
socket_id,
201240
max_threads_per_core);
@@ -205,7 +244,7 @@ struct CPUStreamsExecutor::Impl {
205244
create_tbb_task_arena(stream_id,
206245
stream_type,
207246
concurrency,
208-
cpu_core_type,
247+
cpu_core_types,
209248
numa_node_id,
210249
socket_id,
211250
max_threads_per_core);

src/inference/src/dev/threading/cpu_streams_executor_internal.cpp

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,33 @@ namespace threading {
1515

1616
void get_cur_stream_info(const int stream_id,
1717
const bool cpu_pinning,
18-
const std::vector<std::vector<int>> proc_type_table,
19-
const std::vector<std::vector<int>> streams_info_table,
18+
const std::vector<std::vector<int>>& proc_type_table,
19+
const std::vector<std::vector<int>>& streams_info_table,
2020
StreamCreateType& stream_type,
2121
int& concurrency,
22-
int& core_type,
22+
std::vector<int>& core_types,
2323
int& numa_node_id,
2424
int& socket_id,
2525
int& max_threads_per_core) {
26+
const auto append_core_type = [](std::vector<int>& proc_core_types, int proc_core_type) {
27+
if (std::find(proc_core_types.begin(), proc_core_types.end(), proc_core_type) == proc_core_types.end()) {
28+
proc_core_types.push_back(proc_core_type);
29+
}
30+
};
31+
const auto get_bindable_core_type_count = [](const std::vector<std::vector<int>>& available_proc_type_table) {
32+
if (available_proc_type_table.empty()) {
33+
return 0;
34+
}
35+
36+
return static_cast<int>(available_proc_type_table[0][MAIN_CORE_PROC] > 0) +
37+
static_cast<int>(available_proc_type_table[0][EFFICIENT_CORE_PROC] > 0) +
38+
static_cast<int>(available_proc_type_table[0][LP_EFFICIENT_CORE_PROC] > 0);
39+
};
40+
2641
int stream_total = 0;
2742
size_t stream_info_id = 0;
2843
bool pinning = cpu_pinning;
29-
bool ecore_used = false;
44+
core_types.clear();
3045
for (size_t i = 0; i < streams_info_table.size(); i++) {
3146
stream_total += std::abs(streams_info_table[i][NUMBER_OF_STREAMS]);
3247
if (stream_id < stream_total) {
@@ -35,42 +50,46 @@ void get_cur_stream_info(const int stream_id,
3550
}
3651
}
3752
concurrency = streams_info_table[stream_info_id][THREADS_PER_STREAM];
38-
core_type = streams_info_table[stream_info_id][PROC_TYPE];
53+
int core_type = streams_info_table[stream_info_id][PROC_TYPE];
3954
numa_node_id = streams_info_table[stream_info_id][STREAM_NUMA_NODE_ID];
4055
socket_id = streams_info_table[stream_info_id][STREAM_SOCKET_ID];
4156
max_threads_per_core = 1;
4257
if (core_type == ALL_PROC) {
4358
for (size_t i = stream_info_id + 1; i < streams_info_table.size(); i++) {
4459
if (streams_info_table[i][NUMBER_OF_STREAMS] == 0) {
45-
if (streams_info_table[i][PROC_TYPE] == EFFICIENT_CORE_PROC) {
46-
ecore_used = true;
47-
} else if (streams_info_table[i][PROC_TYPE] == HYPER_THREADING_PROC) {
60+
if (streams_info_table[i][PROC_TYPE] == HYPER_THREADING_PROC) {
4861
max_threads_per_core = 2;
62+
append_core_type(core_types, MAIN_CORE_PROC);
63+
} else {
64+
append_core_type(core_types, streams_info_table[i][PROC_TYPE]);
4965
}
5066
} else {
5167
break;
5268
}
5369
}
5470
} else if (core_type == HYPER_THREADING_PROC) {
5571
max_threads_per_core = 2;
72+
append_core_type(core_types, MAIN_CORE_PROC);
5673
}
5774

5875
#if defined(__APPLE__)
5976
pinning = false;
6077
#endif
78+
if (core_type != ALL_PROC && core_types.empty()) {
79+
append_core_type(core_types, core_type == HYPER_THREADING_PROC ? MAIN_CORE_PROC : core_type);
80+
}
81+
6182
if (pinning) {
6283
stream_type = STREAM_WITH_OBSERVE;
6384
} else {
6485
stream_type = STREAM_WITHOUT_PARAM;
6586
// Pcore only or Ecore only with no cpu binding in hybrid cores machine
66-
if ((proc_type_table[0][EFFICIENT_CORE_PROC] > 0 || proc_type_table[0][LP_EFFICIENT_CORE_PROC] > 0) &&
67-
core_type != ALL_PROC) {
68-
stream_type = STREAM_WITH_CORE_TYPE;
69-
} else if ((proc_type_table[0][EFFICIENT_CORE_PROC] > 0 || proc_type_table[0][LP_EFFICIENT_CORE_PROC] > 0) &&
70-
core_type == ALL_PROC &&
71-
!ecore_used) { // Latency mode and enable hyper threading in hybrid cores machine
72-
stream_type = STREAM_WITH_CORE_TYPE;
73-
core_type = MAIN_CORE_PROC;
87+
if (!proc_type_table.empty() &&
88+
(proc_type_table[0][EFFICIENT_CORE_PROC] > 0 || proc_type_table[0][LP_EFFICIENT_CORE_PROC] > 0)) {
89+
const auto bindable_core_types = get_bindable_core_type_count(proc_type_table);
90+
if (!core_types.empty() && core_types.size() < static_cast<size_t>(bindable_core_types)) {
91+
stream_type = STREAM_WITH_CORE_TYPE;
92+
}
7493
} else if (proc_type_table.size() > 1 && numa_node_id >= 0 &&
7594
// Both commands "numactl" and "docker run --cpuset-cpus" can restrict the use of numa nodes.
7695
// Some situation of numa_node_id differs from the original numa_node_id may cause oneTBB to crash

src/inference/src/dev/threading/parallel_custom_arena.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
// In this case, tbbbind static library is needed.
3030
# define USE_TBBBIND_2_5 TBBBIND_2_5_AVAILABLE
3131

32-
constexpr int MIN_CORE_TYPES_FOR_PTL = 3;
3332
constexpr int TBB_VERSION_MAJOR_CORE_TYPES_WINDOWS = 1202;
3433
constexpr int TBB_VERSION_PATCH_CORE_TYPES_WINDOWS = 6;
3534
constexpr int TBB_VERSION_MAJOR_CORE_TYPES_LINUX = 1213;

0 commit comments

Comments
 (0)