ソフトウェアのパイプライン化 (SWP) レポート (Linux* および Windows*)

ソフトウェアのパイプライン化 (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 ではないループでパフォーマンス問題が発生していることが示され、他に明らかな原因が見当たらない場合、インデックス変数を変更してみてください。