namespace std::execution {
class parallel_scheduler { unspecified };
}
概要
parallel_schedulerは、実行制御ライブラリ上でタスクの並列実行を可能とする並列Schedulerである。
parallel_schedulerはグローバルなスレッドプール(実行リソース)に関連付けられ、schedule操作により得られるSenderはスレッドプールに属する任意のスレッド(実行エージェント)上で実行される。
下記のSenderアルゴリズムに対してカスタマイズ実装を提供することで、タスクの一括(bulk)実行をスレッドプールを利用したタスク並列(parallel)実行に変換する。
execution::bulk:bulk_chunkedに変換してタスク並列実行execution::bulk_chunked: インデクス範囲をチャンク単位でタスク並列実行execution::bulk_unchunked: インデクス範囲を要素単位でタスク並列実行
execution::parallel_scheduler_replacement 名前空間で定義されるインタフェースを介して、スレッドプール実装をユーザ定義の並列Schedulerバックエンドに置き換えることもできる。
クラス仕様
parallel_schedulerはschedulerのモデルである。
説明用のschをparallel_scheduler型のオブジェクト、schがptrと関連付けられるときBACKEND-OF(sch)を*ptrとする。
式get_forward_progress_guarantee(sch)はforward_progress_guarantee::parallelを返す。
説明用のsch2をparallel_scheduler型のオブジェクトとしたとき、BACKEND-OF(sch)とBACKEND-OF(sch2)が同一オブジェクトを指す場合に限って、2つのオブジェクトschとsch2は等しい。
rcvrをReceiverとしたとき、基底Bを持つrcvrのプロキシは下記を満たすB型の左辺値rとなる。
r.set_value()は、set_value(std::move(rcvr))と同じ効果。r.set_error(e)は、eをexception_ptrとして、set_error(std::move(rcvr), std::move(e))と同じ効果。r.set_stopped()は、set_stopped(std::move(rcvr))と同じ効果。
プロキシrに対する事前確保バックエンドストレージ(preallocated backend storage)は、span<byte>型のオブジェクトsであり、rに対してset_value/set_error/set_stoppedいずれかが呼び出されるまで範囲sは有効かつ上書き可能である。
式get_domain(sch)は、下記と等価な説明専用の型parallel-scheduler-domainの式を返す。
struct parallel-scheduler-domain {
template<sender-for<bulk_chunked_t> Sndr, queryable Env>
static constexpr decltype(auto)
transform_sender(set_value_t, Sndr&& sndr, const Env& env) const noexcept {
return see below;
}
template<sender-for<bulk_unchunked_t> Sndr, queryable Env>
static constexpr decltype(auto)
transform_sender(set_value_t, Sndr&& sndr, const Env& env) const noexcept {
return see below;
}
};
上記transform_senderの引数sndrに対して、説明用の変数child, pol, shape, fを下記の通り宣言する。
auto& [_, data, child] = sndr;
auto& [pol, shape, f] = data;
説明用のpを下記とする。
- 式
polの型がCV修飾されたparallel_policyまたはparallel_unsequenced_policyのとき、true。 polが処理系定義の実行ポリシーのとき、処理系定義の値。- そうでなければ、
false。
scheduleアルゴリズム
説明用のbをBACKEND-OF(sch)、sndrをschedule(sch)が返すオブジェクト、rcvrをReceiverとする。rcvrがsndrに接続(connect)され、結果のOperation Stateが開始(start)されたとき、
sndrが値完了するならば、b.schedule(r, s)が呼ばれる。このとき、rは基底クラスparallel_scheduler_replacement::receiver_proxyを持つrcvrのプロキシであり、かつsはrに対する事前確保バックエンドストレージである。
- 他の全ての完了操作は、変更なしに転送される。
bulk_chunkedアルゴリズム
タグbulk_chunked_tとSenderを受け付けるtransform_senderオーバーロードは、Receiverrcvrと接続(connect)され結果のOperation Stateが開始(start)されたとき、下記動作を行うSenderを返す。
childが値valsで値完了するならば、argsをvalsを指す左辺値式のパックとして、b.schedule_bulk_chunked(p ? shape : 1, r, s)が呼ばれる。このとき、rは基底クラスparallel_scheduler_replacement::bulk_item_receiver_proxyを持つrcvrのプロキシであり、インデックスi,jに対してr.execute(i, j)はpがtrueのときf(i, j, args...)、そうでないときはf(0, shape, args...)と等価な効果を持つ。かつsはrに対する事前確保バックエンドストレージである。
- 他の全ての完了操作は、変更なしに転送される。
bulk_unchunkedアルゴリズム
タグbulk_unchunked_tとSenderを受け付けるtransform_senderオーバーロードは、Receiverrcvrと接続(connect)され結果のOperation Stateが開始(start)されたとき、下記動作を行うSenderを返す。
childが値valsで値完了するならば、argsをvalsを指す左辺値式のパックとして、b.schedule_bulk_unchunked(p ? shape : 1, r, s)が呼ばれる。このとき、rは基底クラスparallel_scheduler_replacement::bulk_item_receiver_proxyを持つrcvrのプロキシであり、インデックスiに対してr.execute(i, i + 1)はpがtrueのときf(i, args...)、そうでないときはfor (decltype(shape) i = 0; i < shape; i++) { f(i, args...); }と等価な効果を持つ。かつsはrに対する事前確保バックエンドストレージである。
- 他の全ての完了操作は、変更なしに転送される。
例
#include <concepts>
#include <execution>
namespace ex = std::execution;
int main()
{
ex::scheduler auto sch = ex::get_parallel_scheduler();
static_assert(std::same_as<decltype(sch), ex::parallel_scheduler>);
}
出力
バージョン
言語
- C++26
処理系
- Clang: ??
- GCC: ??
- ICC: ??
- Visual C++: ??