task_arena#
[scheduler.task_arena]
A class that represents an explicit, user-managed task scheduler arena.
// Defined in header <oneapi/tbb/task_arena.h>
namespace oneapi {
namespace tbb {
class task_arena {
public:
static const int automatic = /* unspecified */;
static const int not_initialized = /* unspecified */;
enum class priority : /* unspecified type */ {
low = /* unspecified */,
normal = /* unspecified */,
high = /* unspecified */
};
struct constraints {
constraints(numa_node_id numa_node_ = task_arena::automatic,
int max_concurrency_ = task_arena::automatic);
constraints& set_numa_id(numa_node_id id);
constraints& set_max_concurrency(int maximal_concurrency);
constraints& set_core_type(core_type_id id);
constraints& set_max_threads_per_core(int threads_number);
numa_node_id numa_id = task_arena::automatic;
int max_concurrency = task_arena::automatic;
core_type_id core_type = task_arena::automatic;
int max_threads_per_core = task_arena::automatic;
};
task_arena(int max_concurrency = automatic, unsigned reserved_for_masters = 1,
priority a_priority = priority::normal);
task_arena(constraints a_constraints, unsigned reserved_for_masters = 1,
priority a_priority = priority::normal);
task_arena(const task_arena &s);
explicit task_arena(oneapi::tbb::attach);
~task_arena();
void initialize();
void initialize(int max_concurrency, unsigned reserved_for_masters = 1,
priority a_priority = priority::normal);
void initialize(constraints a_constraints, unsigned reserved_for_masters = 1,
priority a_priority = priority::normal);
void initialize(oneapi::tbb::attach);
void terminate();
bool is_active() const;
int max_concurrency() const;
template<typename F> auto execute(F&& f) -> decltype(f());
template<typename F> void enqueue(F&& f);
void enqueue(task_handle&& h);
};
} // namespace tbb
} // namespace oneapi
A task_arena
class represents a place where threads may share and execute tasks.
The number of threads that may simultaneously execute tasks in a task_arena
is limited by its concurrency level.
Each user thread that invokes any parallel construction outside an explicit task_arena
uses an implicit
task arena representation object associated with the calling thread.
The tasks spawned or enqueued into one arena cannot be executed in another arena.
Each task_arena
has a priority
. The tasks from task_arena
with higher priority are given
a precedence in execution over the tasks from task_arena
with lower priority.
Note
The task_arena
constructors do not create an internal task arena representation object.
It may already exist in case of the “attaching” constructor; otherwise, it is created
by an explicit call to task_arena::initialize
or lazily on first use.
Member types and constants#
-
static const int automatic#
When passed as
max_concurrency
to the specific constructor, arena concurrency is automatically set based on the hardware configuration.
-
static const int not_initialized#
When returned by a method or function, indicates that there is no active
task_arena
or that thetask_arena
object has not yet been initialized.
-
enum priority::low#
When passed to a constructor or the
initialize
method, the initializedtask_arena
has a lowered priority.
-
enum priority::normal#
When passed to a constructor or the
initialize
method, the initializedtask_arena
has regular priority.
-
enum priority::high#
When passed to a constructor or the
initialize
method, the initializedtask_arena
has a raised priority.
-
struct constraints#
Represents limitations applied to threads within
task_arena
.Starting from C++20 this class should be an aggregate type to support the designated initialization.
-
numa_node_id constraints::numa_id#
An integral logical index uniquely identifying a NUMA node. If set to non-automatic value, then this NUMA node will be considered as preferred for all the threads within the arena.
Note
NUMA node ID is considered valid if it was obtained through tbb::info::numa_nodes().
-
int constraints::max_concurrency#
The maximum number of threads that can participate in work processing within the
task_arena
at the same time.
-
core_type_id constraints::core_type#
An integral logical index uniquely identifying a core type. If set to non-automatic value, then this core type will be considered as preferred for all the threads within the arena.
Note
core type ID is considered valid if it was obtained through
tbb::info::core_types()
.
-
int constraints::max_threads_per_core#
The maximum number of threads that can be scheduled to one core simultaneously.
-
constraints::constraints(numa_node_id numa_node_ = task_arena::automatic, int max_concurrency_ = task_arena::automatic)#
Constructs the constraints object with the provided numa_id and max_concurrency settings.
Note
To support designated initialization this constructor is omitted starting from C++20. Aggregate initialization is supposed to be used instead.
-
constraints &constraints::set_numa_id(numa_node_id id)#
Sets the numa_id to the provided
id
. Returns the reference to the updated constraints object.
-
constraints &constraints::set_max_concurrency(int maximal_concurrency)#
Sets the max_concurrency to the provided
maximal_concurrency
. Returns the reference to the updated constraints object.
-
constraints &constraints::set_core_type(core_type_id id)#
Sets the core_type to the provided
id
. Returns the reference to the updated constraints object.
-
constraints &constraints::set_max_threads_per_core(int threads_number)#
Sets the max_threads_per_core to the provided
threads_number
. Returns the reference to the updated constraints object.
Member functions#
-
task_arena(int max_concurrency = automatic, unsigned reserved_for_masters = 1, priority a_priority = priority::normal)#
Creates a
task_arena
with a certain concurrency limit (max_concurrency
) and priority (a_priority
). Some portion of the limit can be reserved for application threads withreserved_for_masters
. The amount for reservation cannot exceed the limit.Caution
If
max_concurrency
andreserved_for_masters
are explicitly set to be equal and greater than 1, oneTBB worker threads will never join the arena. As a result, the execution guarantee for enqueued tasks is not valid in such arena. Do not usetask_arena::enqueue()
with an arena set to have no worker threads.
-
task_arena(constraints a_constraints, unsigned reserved_for_masters = 1, priority a_priority = priority::normal)#
Creates a
task_arena
with a certain constraints(a_constraints
) and priority (a_priority
). Some portion of the limit can be reserved for application threads withreserved_for_masters
. The amount for reservation cannot exceed the concurrency limit specified inconstraints
.Caution
If
constraints::max_concurrency
andreserved_for_masters
are explicitly set to be equal and greater than 1, oneTBB worker threads will never join the arena. As a result, the execution guarantee for enqueued tasks is not valid in such arena. Do not usetask_arena::enqueue()
with an arena set to have no worker threads.If
constraints::numa_node
is specified, then all threads that enter the arena are automatically pinned to corresponding NUMA node.
-
task_arena(const task_arena&)#
Copies settings from another
task_arena
instance.
-
explicit task_arena(oneapi::tbb::attach)#
Creates an instance of
task_arena
that is connected to the internal task arena representation currently used by the calling thread. If no such arena exists yet, creates atask_arena
with default parameters.Note
Unlike other constructors, this one automatically initializes the new
task_arena
when connecting to an already existing arena.
-
~task_arena()#
Destroys the
task_arena
instance, but the destruction may not be synchronized with any task execution inside thistask_arena
. It means that an internal task arena representation associated with thistask_arena
instance can be destroyed later. Not thread-safe for concurrent invocations of other methods.
-
void initialize()#
Performs actual initialization of internal task arena representation.
Note
After the call to
initialize
, the arena parameters are fixed and cannot be changed.
-
void initialize(int max_concurrency, unsigned reserved_for_masters = 1, priority a_priority = priority::normal)#
Same as above, but overrides previous arena parameters.
-
void initialize(constraints a_constraints, unsigned reserved_for_masters = 1, priority a_priority = priority::normal)#
Same as above.
-
void initialize(oneapi::tbb::attach)#
If an internal task arena representation currently used by the calling thread, the method ignores arena parameters and connects
task_arena
to that internal task arena representation. The method has no effect when called for an already initializedtask_arena
.
-
void terminate()#
Removes the reference to the internal task arena representation without destroying the task_arena object, which can then be re-used. Not thread safe for concurrent invocations of other methods.
-
bool is_active() const#
Returns
true
if thetask_arena
has been initialized;false
, otherwise.
-
int max_concurrency() const#
Returns the concurrency level of the
task_arena
. Does not require thetask_arena
to be initialized and does not perform initialization.
-
template<F>
void enqueue(F &&f)# Enqueues a task into the
task_arena
to process the specified functor and immediately returns. TheF
type must meet the Function Objects requirements described in the [function.objects] section of the ISO C++ standard. The task is scheduled for eventual execution by a worker thread even if no thread ever explicitly waits for the task to complete. If the total number of worker threads is zero, a special additional worker thread is created to execute enqueued tasks.Note
The method does not require the calling thread to join the arena; that is, any number of threads outside of the arena can submit work to it without blocking.
Caution
There is no guarantee that tasks enqueued into an arena execute concurrently with respect to any other tasks there.
Caution
An exception thrown and not caught in the functor results in undefined behavior.
-
template<F>
auto execute(F &&f) -> decltype(f())# Executes the specified functor in the
task_arena
and returns the value returned by the functor. TheF
type must meet the Function Objects requirements described in the [function.objects] section of the ISO C++ standard.The calling thread joins the
task_arena
if possible, and executes the functor. Upon return it restores the previous task scheduler state and floating-point settings.If joining the
task_arena
is not possible, the call wraps the functor into a task, enqueues it into the arena, waits using an OS kernel synchronization object for another opportunity to join, and finishes after the task completion.An exception thrown in the functor will be captured and re-thrown from
execute
.Note
Any number of threads outside of the arena can submit work to the arena and be blocked. However, only the maximal number of threads specified for the arena can participate in executing the work.
-
void enqueue(task_handle &&h)#
Enqueues a task owned by
h
into thetask_arena
for processing.The behavior of this function is identical to the generic version (
template<typename F> void task_arena::enqueue(F&& f)
), except parameter type.Note
h
should not be empty to avoid an undefined behavior.
Example#
The example demonstrates task_arena
NUMA support API. Each constructed task_arena
is pinned
to the corresponding NUMA node.
#include "oneapi/tbb/task_group.h"
#include "oneapi/tbb/task_arena.h"
#include <vector>
int main() {
std::vector<oneapi::tbb::numa_node_id> numa_nodes = oneapi::tbb::info::numa_nodes();
std::vector<oneapi::tbb::task_arena> arenas(numa_nodes.size());
std::vector<oneapi::tbb::task_group> task_groups(numa_nodes.size());
for (int i = 0; i < numa_nodes.size(); i++) {
arenas[i].initialize(oneapi::tbb::task_arena::constraints(numa_nodes[i]));
}
for (int i = 0; i < numa_nodes.size(); i++) {
arenas[i].execute([&task_groups, i] {
task_groups[i].run([] {
/* executed by the thread pinned to specified NUMA node */
});
});
}
for (int i = 0; i < numa_nodes.size(); i++) {
arenas[i].execute([&task_groups, i] {
task_groups[i].wait();
});
}
return 0;
}
See also: