ナビゲーションリンクをスキップ | |
印刷ビューの終了 | |
Oracle Solaris Studio 12.3: OpenMP API ユーザーガイド Oracle Solaris Studio 12.3 Information Library (日本語) |
タスク化の機能を利用すると、再帰的な構造や while ループのように、作業単位が動的に生成されるようなアプリケーションの並列化が容易になります。
OpenMP では、明示的 タスクを task 指令を使って指定します。task 指令は、タスクとそのデータ環境に関連づけられたコードを定義します。タスクのコンストラクトは、プログラムのどこに置いてもかまいません。スレッドがタスクコンストラクトを検出すると、新しいタスクが生成されます。
スレッドがタスクコンストラクトを検出すると、スレッドはそれをすぐに実行するか、実行を延期して後で実行するかを選択することがあります。タスクの実行が保留されると、そのタスクは現在の並列領域に関連づけられた概念上のタスクプールに置かれます。現在のチームに属するスレッドは、プールからタスクを取り出し実行するという処理を、プールが空になるまで繰り返します。タスクを実行するスレッドは、タスクを検出した元のスレッドとは異なる場合があります。
タスクコンストラクトに関連づけられたコードは、1 回だけ実行されます。コードが最初から最後まで同じスレッドにより実行されると、タスクは結合されます。コードが複数のスレッドにより実行可能な場合は、タスクは結合解除されます。この場合、コードの異なる部分が別のスレッドにより実行されます。デフォルトでは、タスクは結合されていますが、untied 節を task 指令で使用することにより、結合解除に指定することができます。
スレッドは、タスクのスケジューリングポイントでタスク領域の実行を中断して、異なるタスクを実行することができます。中断されたタスクが結合されている場合は、同じスレッドにより中断されたタスクの実行が後に再開されます。中断されたタスクが結合されていない場合は、現在のチームに属するスレッドならどれでもタスクの実行を再開できます。
OpenMP 仕様には、結合されたタスクに対して次のタスクスケジューリングポイントが定義されています。
task コンストラクトを検出したポイント
taskwait コンストラクトを検出したポイント
taskyield コンストラクトを検出したポイント
暗黙的または明示的なバリアーを検出したポイント
タスクの終了ポイント
Oracle Solaris Studio コンパイラによる実装に従い、これらのスケジューリングポイントは結合解除されたタスクのタスクスケジューリングポイントでもあります。
task 指令を使って指定された明示的タスクに加え、OpenMP 仕様では暗黙的タスクの概念も取り入れられています。暗黙的タスクは、暗黙的な並列領域により生成されるタスク、または実行中に並列構文を検出したときに生成されるタスクです。それぞれの暗黙的タスクのコードは、parallel コンストラクトの内部コードです。暗黙的タスクはそれぞれチーム内の異なるスレッドに割り当てられ、結合されます。すなわち、暗黙的タスクは最初から最後まで常に最初に割り当てられたスレッドにより実行されます。
parallel コンストラクトが検出されたときに生成されたすべての暗黙的タスクは、マスタースレッドが並列領域の最後で暗黙的バリアーを終了するときに完了することが保証されます。一方、並列領域内に生成されるすべての明示的タスクは、並列領域内の次の暗黙的または明示的バリアーの終了時に完了することが保証されます。
OpenMP 3.1 仕様では、タスク化のオーバーヘッドを減らすためにプログラマが選択できる各種のタスクが定義されています。
非延期タスクは、その生成元のタスク領域に対して遅延なく実行されるタスクです。つまり、その生成元のタスク領域は、非延期タスクの実行が完了するまで中断されます。非延期タスクの一例は、false と評価される if 節の式を含むタスクです。この場合、非延期タスクが生成され、検出したスレッドは現在のタスク領域を中断する必要があり、その実行は if 節を含むタスクが完了するまで再開できません。
インクルードタスクは、生成元のタスク領域内で順次実行されるタスクです。つまり、検出したスレッドによって遅延なくただちに実行されます。インクルードタスクの一例は、最終タスク (後述) の子孫であるタスクです。
インクルードタスクと非延期タスクの違いはわずかです。非延期タスクの場合、生成元のタスク領域は非延期タスクが完了するまで中断されますが、非延期タスクは検出直後に実行されるとは限りません。非延期タスクは、検出したスレッドまたはほかのスレッドによって概念上のプールに置かれ、あとで実行されることがあります。その間、生成元のタスクは中断されます。非延期タスクの実行が完了したら、生成元タスクを再開できます。
インクルードタスクの場合、インクルードタスクはそれを検出したスレッドにより、検出直後に実行されます。タスクはあとで実行するためにプールに置かれることはありません。生成元のタスクは、インクルードタスクの実行が完了するまで中断されます。インクルードタスクの実行が完了したら、生成元タスクを再開できます。
マージタスクは、その生成元のタスク領域と同じデータ環境を持つタスクです。task コンストラクトに mergeable 節が存在し、生成されるタスクが非延期タスクまたはインクルードタスクの場合、実装では代わりにマージタスクを生成することができます。マージタスクが生成される場合は、task 指令がまったく存在しないかのように動作します。
最終タスクは、そのすべての子タスクを強制的に最終タスクかつインクルードタスクにするタスクです。task コンストラクトに final 節が存在し、final 節の式が TRUE と評価される場合、生成されるタスクは最終タスクになります。その最終タスクの子孫はすべて、最終タスクかつインクルードタスクになります。