インテル® TBB 2020 の有用な機能: タスク・スケジューラー

インテル® oneTBB

この記事は、インテル® デベロッパー・ゾーンに公開されている『Intel® Threading Building Blocks Documentation』の「Task Scheduler」(https://software.intel.com/en-us/node/506294) の日本語参考訳です。


インテル® スレッディング・ビルディング・ブロック (インテル® TBB) は、アルゴリズム・テンプレートとタスクグループを動かすエンジンであるタスク・スケジューラーを提供します。直接呼び出すことも可能です。タスク・スケジューラーは多くの処理を行うため、タスクの使用は多くの場合、スレッドの使用よりも単純で効率的です。

タスクは計算の論理ユニットです。スケジューラーは、物理スレッドにタスクをマップします。マッピングはノンプリエンプティブです。各タスクには、execute() メソッドがあります。スレッドが execute() の実行を開始すると、タスクは execute() からリターンするまでそのスレッドにバインドされます。その間、スレッドは以下に説明するように、子タスクまたは入れ子になった並列構造の完了を待機する場合にのみ、他のタスクを処理します。待機中は、このスレッドまたは他のスレッドによって生成された関連性のないタスクを含む、利用可能なタスクを実行できます。

タスク・スケジューラーは、計算主体のワークを並列化するように設計されています。タスク・オブジェクトはプリエンプティブにスケジュールされないため、スレッドがほかのタスクを処理できない間、スレッドを長い間ブロックする呼び出しを行ってはなりません。

注意

スケジューラーは利用可能なワーカースレッドに収まるように実際の並列処理を調整するため、「潜在的に」並列可能なタスクが「実際に」並列実行される保証はありません。例えば、単一のワーカースレッドが提供された場合、スケジューラーは並列処理を行えません。さらに、生産タスクの実行中に消費タスクがこの作業を行う保証がないため、生産タスクと消費タスク間でタスクを使用することは安全ではありません。

潜在的な並列処理は通常、分割/結合 パターンによって構成され、2 つの基本パターンがサポートされています。最も効率的なのは、プログラマーが明示的に “継続” タスクを構築する継続渡しです。親は子タスクを生成して、子が完了するときに実行する継続タスクを指定します。継続は親の先祖を継承します。その後、親タスクは終了します。つまり、子をブロックしません。続いて子が実行され、子 (またはその継続) が終了した後、継続タスクが実行を開始します。次の図は、一連のステップを示しています。各ステップの実行タスクは色付きで表示されています。

継続渡しスタイル

明示的な継続渡しは、タスクからスレッドのスタックを分離するので効率的です。しかし、プログラムはより難しくなります。2 つ目のパターンは、暗黙的な継続を使用する “ブロックスタイル” です。このパターンはパフォーマンスの点では効率が落ちますが、プログラムはより簡単です。このパターンでは、下記の図で示されているように、親タスクはその子が完了するまでブロックします。

ブロックスタイル

便利さには代償がつきものです。ブロックされた親タスクがスタックに残っている間、スレッドは別のタスクをスチールして実行できます。継続してスチールとブロックを行うと、スタックが無制限に伸長する可能性があります。この問題を避けるには、スケジューラーでブロックされたスレッドがスチールを停止するように制限します。この制限により、利用可能な並列処理が制約されパフォーマンスに影響する場合があります。

並列アルゴリズムやフローグラフなど、タスク・スケジューラーで構築された高レベルのインテル® TBB 構造は、再帰的な並列処理には継続パスを使用し並列構造全体の完了にはブロッキングを使用します。

上位トピック: インテル® TBB デベロッパー・リファレンス

関連情報

アルゴリズム
https://software.intel.com/node/6b6a79a4-faef-4c08-b011-be6729c7514c
タスクグループ

フローグラフ
https://software.intel.com/node/c3d00b6c-995a-4a19-9f2d-91b51181540d

コンパイラーの最適化に関する詳細は、最適化に関する注意事項を参照してください。

タイトルとURLをコピーしました