メモリー帯域幅のボトルネックへの対応

このトピックは、自動ルーフライン・グラフを使用して、優先度の高い最適化を決定する方法を紹介するチュートリアルの一部です。

以下のステップを実行します。

このトピックでは、以下について説明します。

時間とハードウェア依存性を考慮して、ここでは事前に収集された解析結果を使用します。

結果のスナップショットを開く

次のいずれかの操作を行います。

最も興味のあるルーフライン・グラフのデータに注目

  1. 表示の切り替えを使用して、[Roofline (ルーフライン)] グラフと [Survey Report (サーベイレポート)] を並べて表示します。

  2. インテル® Advisor ツールバーの [Loops And Functions (ループと関数)] フィルター・ドロップダウンから [Loops (ループ)] を選択します。

    インテル® Advisor: フィルター

  3. [Roofline (ルーフライン)] グラフで次の操作を行います。

    • [Use Single-Threaded Loops (シングルスレッドのループを使用)] チェックボックスをオンにします。

    • インテル® Advisor: ルーフライン・メニュー コントロールをクリックして、すべての SP... ループの [Visibility (可視化)] チェックボックスをオンにします(このサンプルコードの変数はすべて倍精度であるため、単精度のルーフラインを非表示にします)。

      インテル® Advisor: ルーフライン・メニュー

      [Point Colorization (ポイントの色分け)] セクションで [Colors of Point Weight Ranges (ポイントの重み範囲の色)] を選択して、ランタイム別にドットを色分けします (赤、黄、緑)。

      インテル® Advisor: コントロール をクリックして変更を保存します。

    • インテル® Advisor: ルーフライン数値ズーム・コントロール コントロールをクリックします。x 軸のフィールドで既存の値を Backspace キーで消去し、0.1 と 0.4 を入力します。y 軸のフィールドで既存の値を Backspace キーで消去し、7.4 と 45.5 を入力します。インテル® Advisor: 保存コントロール ボタンをクリックして変更を保存します。

ルーフライン・グラフのデータの解釈

インテル® Advisor: ルーフライン・グラフとサーベイレポート

[Roofline (ルーフライン)] グラフの roofline.cpp:295 の main のループを表すドットの位置 (下の赤いドット) に注目してください。これは、(オフスクリーンの) [Scalar Add Peak (スカラー加算ピーク)] ルーフラインの上、および [L2 Bandwidth (L2 帯域幅)] ルーフライン上に配置されます。

なぜこの位置にドットがあるのでしょうか?

考えられる答え: ループのパフォーマンスが L2 キャッシュに関連したメモリー帯域幅のボトルネックによって制限されています。

これを検証するため、以下の操作を行います。

  1. [Survey Report (サーベイレポート)] を確認します。

    • roofline.cpp:295 の main にあるループの [Vectorized Loops/Efficiency (ベクトル化されたループ/効率)] 値が 100% です。

      ベクトル化効率が 100% であるため、このドットは (スクリーンには表示されていない) [Scalar Add Peak (スカラー加算ピーク)] ルーフラインの上にあります。

    • roofline.cpp:295 の main にあるループのデータ行をクリックして、[Source (ソース)] タブで関連するソースコードを表示します。

  2. [Source (ソース)] タブでソースの 89 - 96 行目にスクロールして、関連するデータ構造体の定義を確認すると、配列構造体 (SOA) であることが分かります。

    インテル® Advisor: ソースタブ

SOA はベクトル化効率の良いデータレイアウトですが、このサンプルコードではチュートリアルのデータセットが L1 キャッシュに収まらず、L2 キャッシュからのロードが頻繁に発生します。

roofline.cpp:295 の main にあるループは、実際に L2 キャッシュに関連したメモリー帯域幅のボトルネックによりパフォーマンスが制限されるため、[L2 Bandwidth (L2 帯域幅)] ルーフラインの上にあります。

メモリー帯域幅のボトルネックを解消する

方法として、キャッシュ利用を最適化するためコードを再構成することが考えられます。

roofline.cpp:310 の main にあるループはキャッシュ利用が最適化されているため、このループのドット (前出の[Roofline (ルーフライン)]・グラフの上のドット) は [L2 Bandwidth (L2 帯域幅)] ルーフラインの上にあります。

  1. [Survey Report (サーベイレポート)] で、roofline.cpp:310 の main にあるループのデータ行をクリックします。

  2. [Source (ソース)] タブでソースの 97 - 101 行目にスクロールして、関連するデータ構造体の定義を確認すると、配列構造体配列 (AOSOA) であることが分かります。roofline.cpp:310 の main にあるループが AOSOA データレイアウトである場合、このサンプルコードではチュートリアルのワークロードが 2 つのステップ分割され、それぞれのステップのデータセットは L1 キャッシュに収まります。