@@ -42,18 +42,18 @@ A class that represents an explicit, user-managed task scheduler arena.
4242 int max_threads_per_core = task_arena::automatic;
4343 };
4444
45- task_arena(int max_concurrency = automatic, unsigned reserved_for_masters = 1,
46- priority a_priority = priority::normal);
47- task_arena(constraints a_constraints , unsigned reserved_for_masters = 1,
48- priority a_priority = priority::normal);
45+ task_arena(int max_concurrency = automatic, unsigned reserved_slots = 1,
46+ priority a_priority = priority::normal);
47+ task_arena(constraints constraints_ , unsigned reserved_slots = 1,
48+ priority a_priority = priority::normal);
4949 task_arena(const task_arena &s);
5050 explicit task_arena(oneapi::tbb::attach);
5151 ~task_arena();
5252
5353 void initialize();
54- void initialize(int max_concurrency, unsigned reserved_for_masters = 1,
54+ void initialize(int max_concurrency, unsigned reserved_slots = 1,
5555 priority a_priority = priority::normal);
56- void initialize(constraints a_constraints , unsigned reserved_for_masters = 1,
56+ void initialize(constraints constraints_ , unsigned reserved_slots = 1,
5757 priority a_priority = priority::normal);
5858 void initialize(oneapi::tbb::attach);
5959
@@ -71,6 +71,9 @@ A class that represents an explicit, user-managed task scheduler arena.
7171 task_group_status task_arena::wait_for(task_group& tg);
7272 };
7373
74+ std::vector<task_arena> create_numa_task_arenas(task_arena::constraints constraints_ = {},
75+ unsigned reserved_slots = 0);
76+
7477 } // namespace tbb
7578 } // namespace oneapi
7679
@@ -182,28 +185,28 @@ Member types and constants
182185Member functions
183186----------------
184187
185- .. cpp :function :: task_arena(int max_concurrency = automatic, unsigned reserved_for_masters = 1 , priority a_priority = priority::normal)
188+ .. cpp :function :: task_arena(int max_concurrency = automatic, unsigned reserved_slots = 1 , priority a_priority = priority::normal)
186189
187190 Creates a ``task_arena `` with a certain concurrency limit (``max_concurrency ``) and priority
188191 (``a_priority ``). Some portion of the limit can be reserved for application threads with
189- ``reserved_for_masters ``. The amount for reservation cannot exceed the limit.
192+ ``reserved_slots ``. The amount for reservation cannot exceed the limit.
190193
191194 .. caution ::
192195
193- If ``max_concurrency `` and ``reserved_for_masters `` are
196+ If ``max_concurrency `` and ``reserved_slots `` are
194197 explicitly set to be equal and greater than 1, oneTBB worker threads will never
195198 join the arena. As a result, the execution guarantee for enqueued tasks is not valid
196199 in such arena. Do not use ``task_arena::enqueue() `` with an arena set to have no worker threads.
197200
198- .. cpp :function :: task_arena(constraints a_constraints , unsigned reserved_for_masters = 1 , priority a_priority = priority::normal)
201+ .. cpp :function :: task_arena(constraints constraints_ , unsigned reserved_slots = 1 , priority a_priority = priority::normal)
199202
200- Creates a ``task_arena `` with a certain constraints(``a_constraints ``) and priority
203+ Creates a ``task_arena `` with a certain constraints(``constraints_ ``) and priority
201204 (``a_priority ``). Some portion of the limit can be reserved for application threads with
202- ``reserved_for_masters ``. The amount for reservation cannot exceed the concurrency limit specified in ``constraints ``.
205+ ``reserved_slots ``. The amount for reservation cannot exceed the concurrency limit specified in ``constraints ``.
203206
204207 .. caution ::
205208
206- If ``constraints::max_concurrency `` and ``reserved_for_masters `` are
209+ If ``constraints::max_concurrency `` and ``reserved_slots `` are
207210 explicitly set to be equal and greater than 1, oneTBB worker threads will never
208211 join the arena. As a result, the execution guarantee for enqueued tasks is not valid
209212 in such arena. Do not use ``task_arena::enqueue() `` with an arena set to have no worker threads.
@@ -239,11 +242,11 @@ Member functions
239242
240243 After the call to ``initialize ``, the arena parameters are fixed and cannot be changed.
241244
242- .. cpp :function :: void initialize (int max_concurrency, unsigned reserved_for_masters = 1, priority a_priority = priority::normal)
245+ .. cpp :function :: void initialize (int max_concurrency, unsigned reserved_slots = 1, priority a_priority = priority::normal)
243246
244247 Same as above, but overrides previous arena parameters.
245248
246- .. cpp :function :: void initialize (constraints a_constraints , unsigned reserved_for_masters = 1, priority a_priority = priority::normal)
249+ .. cpp :function :: void initialize (constraints constraints _ , unsigned reserved_slots = 1, priority a_priority = priority::normal)
247250
248251 Same as above.
249252
@@ -329,6 +332,26 @@ Member functions
329332
330333 The behavior of this function is equivalent to ``this->execute([&tg]{ return tg.wait(); }) ``.
331334
335+ Non-member Functions
336+ --------------------
337+
338+ .. cpp :function :: std::vector<task_arena> create_numa_task_arenas (task_arena::constraints constraints _ = {}, unsigned reserved_slots = 0)
339+
340+ Returns a ``std::vector `` of non-initialized ``task_arena `` objects, each bound to a separate NUMA node.
341+ The number of created ``task_arena `` instances is equal to the number of NUMA nodes on the system,
342+ as determined by ``tbb::info::numa_nodes() ``.
343+
344+ If an error occurs during system information discovery,
345+ returns a ``std::vector `` containing a single ``task_arena `` object created as
346+ ``task_arena(constraints_.set_numa_id(task_arena::automatic), reserved_slots) ``.
347+
348+ The ``constraints_ `` argument can be specified to apply additional limitations to threads in
349+ the ``task_arena `` objects. For each created arena, the ``numa_id `` value in ``constraints_ ``
350+ is automatically set to the corresponding NUMA node ID from ``tbb::info::numa_nodes() ``.
351+
352+ The ``reserved_slots `` argument allows reserving a specified number of slots in
353+ each ``task_arena `` object for application threads. By default, no slots are reserved.
354+
332355Example
333356-------
334357
@@ -343,22 +366,21 @@ to the corresponding NUMA node.
343366 #include <vector>
344367
345368 int main() {
346- std::vector<oneapi::tbb::numa_node_id> numa_nodes = oneapi::tbb::info::numa_nodes();
347- std::vector<oneapi::tbb::task_arena> arenas(numa_nodes.size());
348- std::vector<oneapi::tbb::task_group> task_groups(numa_nodes.size());
349-
350- for (int i = 0; i < numa_nodes.size(); i++) {
351- arenas[i].initialize(oneapi::tbb::task_arena::constraints(numa_nodes[i]));
352- }
369+ std::vector<oneapi::tbb::task_arena> arenas = oneapi::tbb::create_numa_task_arenas();
370+ std::vector<oneapi::tbb::task_group> task_groups(arenas.size()-1);
353371
354- for (int i = 0 ; i < numa_nodes .size(); i++) {
372+ for (int i = 1 ; i < arenas .size(); i++) {
355373 arenas[i].enqueue([]{
356374 /* executed by a thread pinned to the specified NUMA node */
357- }, task_groups[i]);
375+ }, task_groups[i-1 ]);
358376 }
359377
360- for (int i = 0; i < numa_nodes.size(); i++) {
361- arenas[i].wait_for(task_groups[i]);
378+ arenas[0].execute([] {
379+ /* executed by the main thread pinned to the NUMA node for arenas[0] */
380+ });
381+
382+ for (int i = 1; i < arenas.size(); i++) {
383+ arenas[i].wait_for(task_groups[i-1]);
362384 }
363385
364386 return 0;
0 commit comments