OpenMP 仕様には、OpenMP タスクスケジューラが従う必要のあるいくつかのタスクスケジューリングの制約が示されています。
インクルードタスクは、生成された直後に実行されます。
新しく結合されたタスクのスケジューリングは、現在スレッドに結合されているタスク領域と、バリア領域で中断されていないタスク領域のセットに制約されます。このセットが空の場合は、新しく結合されたタスクをスケジュールできます。それ以外の場合、新しく結合されたタスクをスケジュールできるのは、それがセット内のすべてのタスクの子孫タスクである場合のみです。
従属タスクは、そのタスク依存関係が満たされるまでスケジュールされないものとします。
式が false と評価される if 節を含む構文によって明示的タスクが生成され、前の制約がすでに満たされている場合、そのタスクは生成された直後に実行されます。
タスクスケジューリングに関するほかの前提条件に依存するプログラムは不適合です。
制約 1 と 4 の 2 つは、OpenMP タスクがただちに実行されるべきケースです。
制約 2 はデッドロックを回避するためのものです。Example 4–2 では、Task A、B、および C は結合されたタスクです。Task A を実行しているスレッドはクリティカルな taskyield 領域に入ろうとしていますが、そのスレッドはそのクリティカル領域に関連付けられたロックの所有権を保持しています。taskyield はタスクスケジューリングポイントであるため、Task A を実行しているスレッドは、Task A を中断して、代わりに別のタスクを実行することを選択できます。Task B と C はタスクプールに入っているものとします。制約 2 によれば、Task B は Task A の子孫ではないため、Task A を実行しているスレッドは Task B を実行できません。この時点でスケジュールできるのは Task C のみです。Task C は Task A の子孫であるからです。
かりに Task A が中断されている間に Task B がスケジュールされるとしたら、Task A が結合されているスレッドは Task B のクリティカル領域に入ることができません。そのスレッドはそのクリティカル領域に関連付けられたロックをすでに保持しているからです。その結果、デッドロックが発生します。制約 2 の目的は、コードが適合しているときにこの種のデッドロックの発生を回避することです。
プログラマが Task C 内でクリティカルなセクションを入れ子にした場合にもデッドロックが発生することがありますが、それはプログラミングエラーであることに注意してください。
使用例 4-2 タスクスケジューリングの制約 2 の例#pragma omp task // Task A { #pragma omp critical { #pragma omp task // Task C { } #pragma omp taskyield } } #pragma omp task // Task B { #pragma omp critical { } }