インテル® Advisor は、シリアルプログラムのデータを収集して解析するように設計されています。インテル® Advisor のスータビリティーと依存関係ツールを使用して、部分的に並列化されたプログラムを調査する前に、このトピックのガイドラインを参照して、それぞれの並列サイトがシングルスレッドのシリアルプログラムとして実行されるようプログラムを変更します。
プログラムの現在のバージョンをシリアルプログラムとして実行するため、スレッド数を 1 に制限する必要があります。シングルスレッドでプログラムを実行するには、次の操作を行います。
インテル® oneAPI スレッディング・ビルディング・ブロック (oneTBB) では、メインスレッドで tbb::task_scheduler_init init(1); オブジェクトを作成して、実行ファイルを再度実行します。次に例を示します。
int main() {
tbb::task_scheduler_init init(1);
// ...プログラムの残りのコード...
return 0;
}
task_scheduler_init の効果は、ユーザーが生成したそれぞれのスレッドに対し個別に適用されます。そのため、プログラムがほかの場所でスレッドを生成する場合、スレッドのライフタイムに適用する tbb::task_scheduler_init init(1); を実行する必要があります。インテル® oneTBB の特定の機能を使用すると、プログラムがシリアル実行されない場合があります。詳細は、oneTBB のドキュメントを参照してください。
OpenMP* では次のいずれかを行います。
プログラムを実行する前に、OpenMP* の環境変数 OMP_NUM_THREADS に 1 を設定します。
OpenMP* プラグマとディレクティブの認識を有効にするコンパイラー・オプションを指定します。Windows* では /Qopenmp、Linux* では -openmp オプションを使用します。
詳細は、コンパイラー・ドキュメントを参照してください。
インテル® Advisor のサイト、タスク、およびロック・アノテーションは、スータビリティーと依存関係ツールで使用されます。すでに並列化されているコード領域に、インテル® Advisor の並列サイトとタスク・アノテーションを追加してマークすることができます。サンプルコード nqueens_cilk.cpp の nqueens_Advisor の例を示します。
...
ANNOTATE_SITE_BEGIN(solve);
cilk_for(int i=0; i<size; i++) {
// 再帰ごとに個別の配列を使用して最初の行のすべての位置を確認
ANNOTATE_ITERATION_TASK(setQueen);
int * queens = new int[size];
setQueen(queens, 0, i);
}
ANNOTATE_SITE_END();必要に応じて、アノテーションをコメントにするか、条件付きコンパイルを使用してプリプロセッサー・ディレクティブを追加します。例えば、#ifdef、#ifndef、および #endif プリプロセッサー・ディレクティブを使用します。
...
// アノテーションを隠すには次の行をコメントにします。
#define ANNOTATE_ON
.
.
.
#ifdef ANNOTATE_ON
ANNOTATE_SITE_BEGIN(solve);
#endif
#ifndef ANNOTATE_ON
// ここに並列コードを追加します。
.
.
#ifdef ANNOTATE_ON
ANNOTATE_SITE_END();
#endif
...
並列フレームワークを追加してテストした後で、アノテーションを削除できます。
インテル® Advisor は、ターゲットのシリアルプログラムのデータを収集して解析するように設計されています。
アノテーションが追加された並列サイト内で 1 つ以上のスレッドを生成する並列コードは、スータビリティーや依存関係ツールのレポートに含まれるデータの信頼性を損ないます。これらのツールを使用するには、それぞれの並列サイトに単一のスレッドのみが含まれている必要があります。動的スケジュールや実行時にワークスチールを使用する並列フレームワークの実行時間は、誤ったソースコードに割り当てられる可能性があります。
サーベイツールでプログラムをプロファイルすると、サーベイレポートの [Self Time (セルフ時間)] は、すべてのスレッドの CPU 時間の合計を示します。しかし、インテル® Advisor はシリアルコードの解析を目的としているため、並列コード内の実行時間が誤った場所に追加されることがあります。例えば、並列領域に入ったスレッドの呼び出しの代わりに、並列フレームワークのランタイムシステムのエントリーポイントに [Self Time (セルフ時間)] が追加されるかもしれません。同様にサーベイレポートで並列コードを調査する際に、エントリーポイントが期待される関数やループではなく、並列フレームワークのランタイムのエントリーポイントになる可能性もあります。また、[サーベイソース] ウィンドウでは、並列コード領域の [Total Time (合計時間)] (および [Loop Time (ループ時間)]) がすべてのスレッドの CPU 時間の合計を示すこともあります。
インテル® Advisor はシリアルコードの解析を目的としているため、スータビリティー・レポートでは次のことが発生する可能性があります。
インテル® Advisor は、タスクとロックを含むすべてのアノテーションで示される並列サイトをシングルスレッドである (並列化されていない) と仮定します。(期待通りに) 並列サイト内を 1 つのスレッドのみが実行すると、そのサイトでは正しい結果が得られます。アプリケーションに複数の並列サイトがあり、1 つ以上のサイトが複数のスレッドで実行されると、次の 2 つの項目が適用されます。
どの並列サイト内であっても複数のスレッドで実行されると、レポートされる [Maximum Program Gain (最大プログラムゲイン)] とサイトの [Impact on Program Gain (プログラムゲインの影響)] 値の信頼性が失われます。正しい結果を得るには、すべての並列サイトを 1 つのスレッドが実行するようにします (「シリアルプログラムとして実行」を参照)。
並列サイト内を複数のスレッドが実行すると、そのサイトの結果は予期できず、その値は信頼性が低くなります。最初のスレッドが並列サイト・アノテーションを実行し、2 番目のスレッドがタスク・アノテーションを実行すると、サイトにはタスクがなく、タスクは並列サイト内で実行されていないように見えます。正しい結果を得るには、それぞれの並列サイトを 1 つのスレッドが実行するようにします (「シリアルプログラムとして実行」を参照)。
サイト内のワークスチール構造は、中断されたサイトやタスクに余分な時間が追加される原因となります。すべてのスータビリティー・レポートの時間は概算です。
同様に、依存関係レポートでは、並列サイトが複数のスレッドを実行すると、依存関係ツールが特定の問題を検出して報告するのを妨げる可能性があります。正しい結果を得るには、それぞれの並列サイトを 1 つのスレッドが実行するようにします (「シリアルプログラムとして実行」を参照)。