ソフトウェアのパイプライン化 (SWP) レポートは、IA-64 アーキテクチャー・ベース・システムでソフトウェアのパイプライン化を現在活用しているループに関する詳細な情報を提供します。レポートでは、ループがパイプライン化されない理由も示唆します。
次のコマンド構文は、Itanium コンパイラーのコード・ジェネレーター (ECG) ソフトウェア・パイプライナー (SWP) 用の SWP レポートを生成する方法を示しています。
プラットフォーム |
構文例 |
---|---|
Linux* |
icpc -c -opt-report -opt-report-phaseecg_swp sample.cpp |
Windows* |
icl /c /Qopt-report /Qopt-report-phase:ecg_swp sample.cpp |
ここで、-c (Linux)、/c (Windows) は、オブジェクト・コードの生成時に停止する (リンクしない) ようにコンパイラーに指示し、-opt-report (Linux)、/Qopt-report (Windows) はレポート・ジェネレーターを起動し、-opt-report-phaseecg_swp (Linux)、/Qopt-report-phase:ecg_swp (Windows) はレポートを生成するフェーズ (ecg) を示します。
-opt-report-file (Linux) または /Qopt-report-file (Windows) を使用して、レポート結果をキャプチャーする出力ファイルを指定します。結果をキャプチャーするファイルを指定することで、結果の解析に費やす時間を短縮でき、後に行うテスティングの基本ラインをつかむことができます。
レポートで、ソフトウェア・パイプライン中のループには、コンパイラーが SWP 用にループをスケジューリングしていたことを示す行が表示されます。-O3 (Linux) または /O3 (Windows) オプションが指定されると、SWP レポートは、ループ最適化機構によって実行されたループ変換サマリーをマージします。
関数呼び出しがループの内部にある場合、一部のループはソフトウェアのパイプライン化が行われず、他のループはベクトル化されません。これらのループをソフトウェアのパイプライン化またはベクトル化する 1 つの方法として、IPO を使用して関数をインライン展開する方法があります。
このサンプルコードを -c -restrict (Linux) および /c /Qrestrict (Windows) の組み合わせを使用してコンパイルすると、サンプル SWP レポートが生成されます。サンプルレポートの内容は、この後に示されています。
例 |
---|
#define NUM 1024 void multiply_d(double a[][NUM], double b[][NUM], double c[restrict][NUM]){ int i,j,k; double temp; for(i=0;i<NUM;i++) { for(j=0;j<NUM;j++) { for(k=0;k<NUM;k++) { c[i][j] = c[i][j] + a[i][k] * b[k][j]; } } } } |
次のサンプルレポートは、上記の例を (ecg_swp フェーズを使用して) コンパイルした結果のレポートフェーズを示しています。
サンプル SWP レポート |
---|
Swp report for loop at line 8 in _Z10multiply_dPA1024_dS0_S0_ in file SWP report.cpp Resource II = 2 Recurrence II = 2 Minimum II = 2 Scheduled II = 2 Estimated GCS II = 7 Percent of Resource II needed by arithmetic ops = 100% Percent of Resource II needed by memory ops = 50% Percent of Resource II needed by floating point ops = 50% Number of stages in the software pipeline = 6 |
SWP レポートの結果を理解するためには、用語と関連する概念について知っておく必要があります。次の表では、SWP レポートで使用される用語を説明します。
用語 |
定義 |
---|---|
II |
初期インターバル (II)。SWP で、ある反復の開始から次の反復の開始までのサイクル数です。SWP レポートに用語 II が含まれている場合、問題のループで SWP が成功したことを意味します。 II は、反復の数がわかっている場合に、ループを実行するサイクル数を決定する簡易計算で使用されます。ループの合計サイクル数は、約 N * Scheduled II + ステージ数 (N はループの反復の数) です。SWP のプロローグおよびエピローグの ramp-up および ramp-down を考慮しないで、SWP ループのカーネルについてのみ考慮しているので、これはあくまでも近似値です。コードを修正するとき、本来は根本的な性能係数であるソフトウェア・パイプライン中の N * Scheduled II + ステージ数を確認するべきですが、一般的には、Scheduled II が下がることを確認するほうがよいでしょう。 |
Resource II |
Resource II は、利用可能な関数ユニットの数を考慮する場合の初期インターバルを示します。 |
Recurrence II |
Recurrence II は、ループに再帰関係がある場合の初期インターバルを示します。再帰関係は、a[i] = a[i-1] (ここで、a[i] は a[i-1] がわかるまで計算できない) のようなフロー依存性と呼ばれる特別な種類のデータ依存性です。Recurrence II がゼロではなく、コードにフロー依存性がない場合、非ユニット・ストライド・アクセスまたはメモリー・エイリアシングのいずれかであることを示します。 詳細は、「コンパイラーの活用」を参照してください。 |
Minimum II |
Minimum II は、達成可能な理論上の最小初期インターバルです。 |
Scheduled II |
Scheduled II は、コンパイラーが SWP 用に実際に予定したものです。 |
number of stages |
ステージ数を示します。例えば、下記のレポート結果で、Number of stages in the software pipeline = 3 は、アセンブリーで 3 つのステージ (ロード、FMA 命令およびストア) があったことを示します。 |
loop-carried memory dependence edges |
ループ運搬のメモリー依存エッジは、コンパイラーが WAR (READ の後の WRITE) 依存を回避したことを意味します。 ループ運搬のメモリー依存エッジは、メモリー・エイリアシングに関する問題を示します。詳細は、「コンパイラーの活用」を参照してください。 |
特定のループがソフトウェア・パイプライン化されたかどうかを素早く判断する方法の 1 つは、レポート出力で "Number of stages in the software pipeline" というフレーズを検索する方法です。このフレーズは、関連するループのソフトウェアのパイプライン化が成功したことを意味します。
SWP していないループを解析して、SWP を有効にするための方法を特定してください。コンパイラーが Loop was not SWP because... とレポートした場合、次の表で問題を解決する方法を参照してください。
レポートのメッセージ |
推奨する処理 |
---|---|
acyclic global scheduler can achieve a better schedule: => loop not pipelined |
最も可能性の高い問題がメモリー・エイリアシング問題であることを示します。メモリー・エイリアシング (restrict, #pragma ivdep) を参照してください。 アプリケーションが非ユニットストライド方式でメモリーにアクセスしている可能性があります。非ユニットストライド問題は、不自然に高い再帰 II で示されます。ループで再帰関係 (a[i] = a[i-1] + b[i]) がないことがわかっている場合、高い再帰 II (0 より大きい) は、非ユニットストライドでメモリーにアクセスしているというサインです。 コードの再配置 (ループ交換) は、この問題を緩和します。 |
Loop body has a function call |
関数のインライン展開が問題の解決に役立つことを示します。 |
Not enough static registers |
ループを 2 つ以上のループに分配するべきであることを示します。 IA-64 アーキテクチャー・ベース・システムでは、#pragma distribute point を使用できます。 |
Not enough rotating registers |
ループ運搬の値が rotating registers (回転レジスター) を使用することを示します。ループを分配します。IA-64 アーキテクチャー・ベース・システムでは、#pragma distribute point を使用できます。 |
Loop too large |
ループを分配するべきであることを示します。 IA-64 アーキテクチャー・ベース・システムでは、#pragma distribute point を使用できます。 |
Loop has a constant trip count < 4 |
アンロールが不十分だったことを示します。ループが完全にアンロールするようにしてください。しかし、小さなループでは、ループが完全にアンロールしてもパフォーマンスに大きく影響することはありません。 |
Too much flow control |
ループ構造が複雑なことを示します。ループを単純にしてください。 |
使用されるインデックス変数型はパフォーマンスに大きく影響します。例えば、short または符号なし int のインデックス変数型を使用すると、ソフトウェアのパイプライン化が妨げられることがあります。レポートでインデックス変数が int ではないループでパフォーマンス問題が発生していることが示され、他に明らかな原因が見当たらない場合、インデックス変数を変更してみてください。