プログラム構造とキャッシュ動作

cachetest のパフォーマンスデータを収集したことを確認してください。 これらの作業が完了していない場合は、cachetest サンプルのデータ収集を参照して実行してください。

ここでは、dgemv_g2 のパフォーマンスが dgemv_g1 のパフォーマンスより優れている理由を検証します。

  1. 「ファイル」 and choose 「実行を開く」を選択して cpi.er を開きます。
  2. 「ファイル」 and choose 「実験ファイルの追加」を選択して dcstall.er を追加します。
  3. 「関数」タブの「ユーザー CPU」と「CPU サイクル」の値を比較します。

    DTLB (Data Translation Lookaside Buffer) のミスのため、dgemv_g1 では差異が生じます。 DTLB のミスが解決されるのを CPU が待っている間、システム時計は動作しますが、サイクルカウンタは停止します。 dgemv_g2 の場合、DTLB のミスはほとんど発生しないので差異は無視できるレベルです。

  4. dgemv_g1dgemv_g2 の D-キャッシュと E-キャッシュのストール時間を比較します。

    キャッシュの再読み込み待ち時間は、dgemv_g2 の方が dgemv_g1 より短くなっています。これは、dgemv_g2 のデータアクセス方法の方がキャッシュを効率よく使用しているからです。

    原因をつきとめるには、注釈付きソースコードを調べます。 まず、表示データを制限するため、ほとんどのメトリックを削除します。

  5. 「表示」and choose「データ表示方法の設定」を選択し、「メトリック」タブの「命令の実行」と「CPU サイクル」のチェックボックスを選択解除します。
  6. 「関数」タブで dgemv_g1 をクリックし、「ソース」タブをクリックします。
  7. dgemv_g1dgemv_g2 の両方のソースが表示できるように画面のサイズを調整してスクロールします。

    2 つのルーチンのループ構造は異なっています。 コードが最適化されていないので、dgemv_g1 の配列のデータには、大きな刻み幅 (ここでは 6000 ) 行単位でアクセスされます。 これが DTLB とキャッシュのミスの原因です。 dgemv_g2 の場合、データへのアクセスは単位刻み幅で列単位で行われます。 各ループ反復のデータは連続しているため、大きいセグメントをマップしキャッシュに読み込むことができます。キャッシュのミスが発生するのは、このセグメントの残量がなくなり別のセグメントが必要になったときだけです。



著作権と商標について