インテル® Advisor ユーザーガイド

アノテーションと OpenMP* コード

ここでは、OpenMP* の並列フレームワーク・コードを追加して、インテル® Advisor アノテーションで推奨された並列処理を実装する手順を説明します。

アノテーションを OpenMP* コードに置き換える際に推奨される手順は以下のとおりです。

  1. LOCK アノテーションをガイドとして、適切な共有リソースの同期を追加します。

  2. 並列タスクを使用して非決定論的な動作を追加する前に、問題がないか検証するためテストを行います。

  3. サイト/タスクのアノテーションをガイドとして、OpenMP* の並列セクションを生成するコードを追加します。

  4. プログラムが正しく動作することを確認するため、単一のスレッドでテストを行います。例えば、プログラムを実行する前に環境変数 OMP_NUM_THREADS を 1 に設定します。

  5. マルチスレッドが期待どおりに動作することを確認するため、複数のスレッドでテストを行います。

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 ! 並列領域終了

関連情報