インテル® Advisor ユーザーガイド
ここでは、OpenMP* の並列フレームワーク・コードを追加して、インテル® Advisor アノテーションで推奨された並列処理を実装する手順を説明します。
適切な共有リソースの同期を追加するため、LOCK アノテーションをガイドとして使用して OpenMP* コードを追加します。「共有リソースを同期するため OpenMP* コードを追加」では、次に示す OpenMP* の同期手法の概要を説明しています。
OpenMP* のタスクを生成するコードを追加するため、サイト/タスクのアノテーションをガイドとして使用します。次のトピックは OpenMP* のタスク生成処理をカバーします。
アノテーションを OpenMP* コードに置き換える際に推奨される手順は以下のとおりです。
LOCK アノテーションをガイドとして、適切な共有リソースの同期を追加します。
並列タスクを使用して非決定論的な動作を追加する前に、問題がないか検証するためテストを行います。
サイト/タスクのアノテーションをガイドとして、OpenMP* の並列セクションを生成するコードを追加します。
プログラムが正しく動作することを確認するため、単一のスレッドでテストを行います。例えば、プログラムを実行する前に環境変数 OMP_NUM_THREADS を 1 に設定します。
マルチスレッドが期待どおりに動作することを確認するため、複数のスレッドでテストを行います。
OpenMP* はワーカースレッドを自動的に生成します。一般に、開発者はタスクについてのみ考え、ワーカースレッドの生成と破棄は並列フレームワークに任せるべきです。
ワーカースレッドの生成と破棄で何らかの制御が必要である場合、コンパイラーのドキュメントを参照してください。例えば、スレッド数を制限するには、OMP_THREAD_LIMIT または OMP_NUM_THREADS 環境変数を設定します。
次の表は、並列処理を適用可能な典型的な例を示します。左のカラムはアノテーションが追加されたシリアルコードで、右のカラムは等価な OpenMP* C/C++ と Fortran 並列コードです。
インテル® Advisor のアノテーションを追加した C/C++ と Fortran シリアルコード | OpenMP* を使用した C/C++ と Fortran 並列コード |
---|---|
// C/C++: 同期 ANNOTATE_LOCK_ACQUIRE(0); Body(); ANNOTATE_LOCK_RELEASE(0); |
// 同期には OpenMP* のクリティカル・セクション、 // atomic 操作、ロック、および reduction 操作 // (以降で説明) を使用できます |
! Fortran: 同期 call annotate_lock_acquire(0) body call annotate_lock_release(0) |
// 同期には OpenMP* のクリティカル・セクション、 // atomic 操作、ロック、および reduction 操作 // (以降で説明) を使用できます |
// データ並列処理 - カウント付き C/C++ // ループ内で 1 つのタスク ANNOTATE_SITE_BEGIN(site); for (i = 0; i < n; ++i) { ANNOTATE_ITERATION_TASK(task); ステートメント; } ANNOTATE_SITE_END(); |
// データ並列処理 - 1 つのタスクの // カウント付き C/C++ ループ #pragma omp parallel for for (int i = 0; i < n; ++i) { ステートメント; } |
! データ並列処理 - カウント付き Fortran ! ループ内の 1 つのタスク call annotate_site_begin("site1") do i = 1, N call annotate_iteration_task("task1") ステートメント end do call annotate_site_end |
! データ並列処理 - 1 つのタスクの ! カウント付き Fortran ループ ! $omp parallel do do i = 1, N ステートメント end do ! $omp end parallel do |
// C/C++ 関数の並列化 ANNOTATE_SITE_BEGIN(site); ANNOTATE_TASK_BEGIN(task1); function_1(); ANNOTATE_TASK_END(); ANNOTATE_TASK_BEGIN(task2); function_2(); ANNOTATE_TASK_END(); ANNOTATE_SITE_END(); |
// C/C++ 関数の並列化 #pragma omp parallel // 並列領域の開始 { #pragma omp sections { #pragma omp section function_1(); #pragma omp section function_2(); } } // 並列領域の終了 |
! Fortran 関数の並列化 call annotate_site_begin("site1") call annotate_task_begin("task1") call subroutine_1 call annotate_task_end call annotate_task_begin("task2") call subroutine_2 call annotate_task_end call annotate_site_end |
! Fortran 関数の並列化 !$omp parallel ! 並列領域開始 !$omp sections !$omp section call subroutine_1 !$omp section call subroutine_2 !$omp end sections !$omp end parallel ! 並列領域終了 |