task_arena

[scheduler.task_arena]

明示的なユーザー管理のタスク・スケジューラーのアリーナを表すクラス。


// <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

task_arena クラスは、スレッドがタスクを共有および実行可能な場所を示します。

task_arena のタスクを同時に実行するスレッド数は平行レベルにより制限されます。

明示的な task_arena の外部で並列構造を呼び出すユーザースレッドは、 呼び出し元のスレッドに関連する暗黙的なタスクアリーナを表現するオブジェクトを使用します。

あるアリーナにスポーンまたは追加されたタスクは、ほかのアリーナでは実行できません。

それぞれの task_arenapriority を持ちます。優先順位の高い task_arena のタスクは、順位の低い task_arena のタスクよりも実行が優先されます。

task_arena コンストラクターは、内部タスクアリーナの表現オブジェクトを作成しません。「アタッチ」コンストラクターはすでに存在している可能性があります。さもなければ、明示的にtask_arena::initialize を呼び出すか、初回の使用時に遅延して作成されます。

メンバーのタイプと定数

static const int automatic

max_concurrency が特定のコンストラクターに渡されると、アリーナの同時実行性はハードウェア構成に基づいて自動的に設定されます。

static const int not_initialized

メソッドまたは関数から返された場合、アクティブな task_arena がないか、task_arena オブジェクトがまだ初期化されていないことを示します。

enum priority::low

コンストラクターまたは initialize メソッドに渡されると、初期化された task_arena の優先順位は低くなります。

enum priority::normal

コンストラクターまたは initializeメソッドに渡されると、初期化された task_arena の優先順位は通常になります。

enum priority::high

コンストラクターまたは initialize メソッドに渡されると、初期化された task_arena の優先順位は髙くなります。

struct constraints

task_arena 内部のスレッドに適用される制限を表現します。

C++20 以降では、このクラスは指定する初期化をサポートする集合体タイプである必要があります。

numa_node_id constraints::numa_id

NUMA ノードを一意に識別する整数論理インデックス。非自動値に設定されている場合、この NUMA ノードはアリーナ内のすべてのスレッドで優先されると見なされます。

NUMA ノード ID は、tbb::info::numa_nodes() を介して取得された場合に有効となります。

int constraints::max_concurrency

task_arena 内で同時に処理するワークに参加できるスレッドの最大数。

core_type_id constraints::core_type

コアタイプを一意に識別する整数論理インデックス。非自動値に設定されている場合、この NUMA ノードはアリーナ内のすべてのスレッドで優先されると見なされます。

コアタイプ ID は、tbb::info::core_types() を介して取得された場合に有効になります。

int constraints::max_threads_per_core

1 つのコアに同時にスケジュールできるスレッドの最大数。

constraints::constraints(numa_node_id numa_node_ = task_arena::automatic, int max_concurrency_ = task_arena::automatic)

指定された numa_idmax_concurrency の設定を使用して、制約オブジェクトを構築します。

指定された初期化をサポートするため、C++20 以降ではこのコンストラクターは除外されます。代わりに集約型の初期化が使用されます。

constraints &constraints::set_numa_id(numa_node_id id)

numa_id を指定された id に設定します。更新された制約オブジェクトの参照を返します。

constraints &constraints::set_max_concurrency(int maximal_concurrency)

max_concurrency を指定された maximal_concurrency に設定します。更新された制約オブジェクトの参照を返します。

constraints &constraints::set_core_type(core_type_id id)

core_type を指定された id に設定します。更新された制約オブジェクトの参照を返します。

constraints &constraints::set_max_threads_per_core(int threads_number)

max_threads_per_core を指定された threads_number に設定します。更新された制約オブジェクトの参照を返します。

メンバー関数

task_arena(int max_concurrency = automatic, unsigned reserved_for_masters = 1, priority a_priority = priority::normal)

特定の同時実行制限 (max_concurrency) と優先順位 (a_priority) で task_arena を作成します。制限の一部は、reserved_for_masters を使用してアプリケーション・スレッド向けに予約できます。予約数は制限を超えることはできません。

警告

max_concurrency および reserved_for_masters が共に等しく 1 以上に設定されている場合、oneTBB のワーカースレッドはアリーナに参加することはありません。その結果、これらのアリーナではキューに投入されたタスクの実行は保証されません。ワーカースレッドなしに設定されたアリーナで task_arena::enqueue() を使用しないでください。

task_arena(constraints a_constraints, unsigned reserved_for_masters = 1, priority a_priority = priority::normal)

特定の制限 (a_constraints) と優先順位 (a_priority) で task_arena を作成します。制限の一部は、reserved_for_masters を使用してアプリケーション・スレッド向けに予約できます。予約数は、constraints で指定された同時実行の制限を超えることはできません。

警告

constraints::max_concurrency および reserved_for_masters が共に等しく 1 以上に設定されている場合、oneTBB のワーカースレッドはアリーナに参加することはありません。その結果、これらのアリーナではキューに投入されたタスクの実行は保証されません。ワーカースレッドなしに設定されたアリーナで task_arena::enqueue() を使用しないでください。

constraints::numa_node が指定されていると、アリーナを実行するすべてのスレッドは、対応する NUMA ノードに自動的にピニングされます。

task_arena(const task_arena&)

別の task_arena インスタンスから設定をコピーします。

explicit task_arena(oneapi::tbb::attach)

呼び出しスレッドで使用されている内部タスクアリーナ表現に接続される task_arena のインスタンスを作成します。アリーナがまだ存在しない場合、デフォルト・パラメーターで task_arena を作成します。

他のコンストラクターとは異なり、すでに存在する領域に接続したとき新しい task_arena は自動的に初期化されます。

~task_arena()

task_arena インスタンスを破棄しますが、破棄はこの task_arena 内のタスクの実行と同期されない場合があります。これは、task_arena インスタンスに関連する内部タスクアリーナ表現を遅延して破棄できることを意味します。ほかのメソッドを同時に呼び出した場合、スレッドセーフではありません。

void initialize()

内部タスクアリーナ表現を初期化します。

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)

呼び出しスレッドで現在使用されている内部タスクアリーナ表現が存在する場合、メソッドはアリーナ・パラメーターを無視して task_arena をその内部タスクアリーナ表現に接続します。すでに初期化されている task_arena に対して呼び出された場合、メソッドは効果がありません。

void terminate()

task_arena オブジェクトを破棄せずに内部タスクアリーナ表現への参照を削除します。この task_arena オブジェクトは再利用できます。他のメソッドの同時に呼び出しに対しスレッドセーフではありません。

bool is_active() const

task_arena が初期化されている場合は true を返し、それ以外は false を返します。

int max_concurrency() const

task_arena の並行レベルを返します。task_arena を初期化する必要がなく、初期化を実行しません。

template<F>
void enqueue(F &&f)

指定されたファンクターを処理するため、タスクを task_arena に追加し直ちにリターンします。F タイプは、[function.objects] ISO C++ 標準の Function Objects の要件を満たしている必要があります。タスクの完了を明示的に待機するスレッドがない場合でも、タスクはワーカースレッドで実行されるようにスケジュールされます。ワーカースレッドの総数がセロである場合、キューに投入されたタスクを実行する特殊なワーカースレッドが生成されます。

メソッドでは、呼び出し元のスレッドはアリーナに参加する必要はありません。つまり、アリーナ外の任意の数のスレッドが、ブロックすることなくアリーナにワークを送信できます。

警告

アリーナのキューに投入されたタスクが、ほかのタスクと同時に実行される保証はありません。

警告

例外がスローされ、ファンクターでキャッチされない場合の動作は未定義です。

template<F>
auto execute(F &&f) -> decltype(f())

指定されるファンクターを task_arena で実行し、ファンクターの戻り値を返します。F タイプは、[function.objects] ISO C++ 標準の Function Objects の要件を満たしている必要があります。

呼び出しスレッドは、可能であれば task_arena に参加してファンクターを実行します。リターンすると、以前のタスク・スケジューラーの状態と浮動小数点設定を復元します。

task_arena へジョインできない場合、ファンクターをタスクにラップしてアリーナのキューに追加し、OS カーネルの同期オブジェクトを使用してジョインする機会を待ち、タスクの完了後に終了します。

ファンクターでスローされた例外はキャプチャーされ、execute から再度スローされます。

アリーナ外の任意の数のスレッドがアリーナにワークを送信できますがブロックされる可能性があります。ただし、ワークを実行できるのは、アリーナで指定されている最大スレッド数までです。

void enqueue(task_handle &&h)

h が所有するタスクを処理するため task_arena にエンキューします。

この関数の動作は、パラメーター・タイプを除き、汎用バージョン (template<typename F> void task_arena::enqueue(F&& f)) と同じです。

未定義の動作を避けるため、h は空であってはなりません。

この例は、task_arena の NUMA サポート API を示します。構築された task_arena は、対応する NUMA ノードに固定されます。


#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; 
}

参照: