Sun Studio 12: OpenMP API ユーザーズガイド

第 6 章 パフォーマンス上の検討事項

正しく機能する OpenMP プログラムを作成したら、その全体のパフォーマンスを検討してみてください。OpenMP アプリケーションの効率性とスケーラビリティーを向上させる際に利用できる一般的なテクニック、および Sun プラットフォームに固有のテクニックがあります。ここでは、そうしたテクニックを簡単に説明します。

更に詳しい内容は、Rajat Garg および Ilya Sharapov 共著の『Techniques for Optimizing Applications: High Performance Computing』を参照してください。この著作は、http://www.sun.com/books/catalog/garg.xml から入手できます。

また、http://developers.sun.com/prodtech/cc/ にある Sun の開発者向けポータルサイトもご覧ください。OpenMP アプリケーションのパフォーマンス解析と最適化に関する記事および事例研究が掲載されていることがあります。

6.1 一般的な推奨事項

OpenMP アプリケーションのパフォーマンスを向上させる一般的なテクニックとして、次のようなものがあります。


効率の劣る構文:

!$OMP PARALLEL
  ....
  !$OMP DO
    ....
  !$OMP END DO
  ....
!$OMP END PARALLEL

!$OMP PARALLEL
  ....
   !$OMP DO
     ....
   !$OMP END DO
  ....
!$OMP END PARALLEL

次のほうが良い:

!$OMP PARALLEL
  ....
  !$OMP DO
    ....
  !$OMP END DO
  .....

  !$OMP DO
    ....
  !$OMP END DO

!$OMP END PARALLEL

効率の劣る構文:

!$OMP PARALLEL
  !$OMP DO
    .....
  !$OMP END DO
!$OMP END PARALLEL

次のほうが良い:

!$OMP PARALLEL DO
   ....
!$OMP END PARALLEL

2 つのループをマージ


!$omp parallel do
  do i = ...

statements_1


  end do
!$omp parallel do
  do i = ...

statements_2


  end do

1 つのループにする


!$omp parallel do
  do i = ...

statements_1

statements_2


  end do

6.2 「偽りの共有」とその回避方法

OpenMP アプリケーションで不注意に共有メモリー構造体を使用すると、パフォーマンスおよびスケーラビリティーが低下することがあります。メモリー上の連続する共有データを複数のプロセッサが更新すると、マルチプロセッサインターコネクタに過度のトラフィックが生じ、結果的に計算の直列化の原因になることがあります。

6.2.1 「偽りの共有」とは

UltraSPARC プロセッサなどの大部分の高性能プロセッサでは、低速のメモリーと CPU の高速レジスタの間にキャッシュバッファーが 1 つ挿入されています。メモリー上の場所にアクセスすると、その要求された場所を含む実際のメモリーのスライス (キャッシュライン) がキャッシュにコピーされます。同じメモリー上の場所またはその周囲の場所への以降の参照は、多くの場合、キャッシュとメモリー間の整合性を維持する必要があるとシステムが判断するまで、キャッシュから満たすことができます。

ただし、同じキャッシュライン内の個々の要素に対する、異なるプロセッサからの同時更新があると、それらの更新が互いに論理的に独立していても、キャッシュライン全体の妥当性が失われます。このため、キャッシュラインの個別要素の更新があると、その都度、そのラインには「無効」のマークが付けられます。同じキャッシュライン上の別の要素にアクセスするほかのプロセッサは、そのラインに「無効」のマークが付いていることを検出します。このため、そのプロセッサは、アクセスしようとする要素が変更されていなくても、メモリーなどの場所からそのラインの最新のコピーをフェッチすることになります。これは、キャッシュ整合性をキャッシュラインのレベルで維持するためであり、個別の要素のためではありません。この結果、インターコネクトのトラフィックとオーバーヘッドが増加することになります。また、キャッシュラインが更新中、そのライン上の要素へのアクセスは禁止されます。

この状態は「偽りの共有」と呼ばれます。頻繁にこの状態になる場合は、OpenMP アプリケーションのパフォーマンスとスケーラビリティーが大幅に低下します。

偽りの共有によってパフォーマンスが低下するのは、次の条件のすべてが満たされる場合です。

ループ内で読み取り専用の共有データは偽りの共有にはならないことに注意してください。

6.2.2 偽りの共有の低減

アプリケーションの実行で主要な役割を果たす並列ループを綿密に分析することによって、偽りの共有によって引き起こされるパフォーマンスおよびスケーラビリティー上の問題を明らかにすることができます。一般に、偽りの共有は次のことを行うことによって減らすことができます。

場合によっては、大きなサイズの問題を処理しているときは共有が少ないために、偽りの共有の影響がわかりにくいことがあります。

偽りの共有を追跡するための技法は、アプリケーションによって大きく異なります。データの割り当て方法を変更すると、偽りの共有が減少する場合があります。スレッドの反復のマッピングを変更し、チャンクごとの各スレッドの作業量を増やす (chunksize 変数を変更する) ことでも、偽りの共有が減少することもあります。

6.3 Solaris OS のチューニング機能

Solaris 9 以降のオペレーティングシステムでは SunFireTM システム向けにスケーラビリティーとパフォーマンス向上が導入されています。中でも、MPO (Memory Placement Optimizations: メモリー配置の最適化) および MPSS (Multiple Page Size Support: 複数ページサイズのサポート) が、ハードウェアのアップグレードなしに OpenMP プログラムのパフォーマンスを向上させる Solaris 9 の新機能として組み込まれました。

MPO によって、OS は、アクセスするプロセッサの近くにあるページをプロセッサに割り当てることができます。SunFire E20K および SunFire E25K システムは、同じ UniBoardTM 内と異なる UniBoard 間でメモリー待ち時間が異なります。「first-touch」というデフォルトの MPO ポリシーでは、メモリーに最初に接触するプロセッサが装着されている UniBoard 上のメモリーが割り当てられます。first-touch ポリシーは、first-touch 配置で、たいていのデータアクセスが各プロセッサにローカルのメモリーに行われるアプリケーションのパフォーマンスを大幅に改善することができます。メモリーがシステム全体に均等に分散されるランダムメモリー配置ポリシーと比較して、アプリケーションのメモリー待ち時間を短縮して帯域幅を増加することができ、その結果、パフォーマンスの向上につながります。

MPSS 機能は Solaris 9 OS リリース以降でサポートされ、プログラムが仮想メモリーの異なる領域で異なるページサイズを使用できます。Solaris のデフォルトのページサイズは比較的小さくなっています (UltraSPARC プロセッサで 8 K バイト、AMD64 Opteron プロセッサで 4 K バイト) 。TLB ミスが多いと影響を受けるアプリケーションでは、大きいページサイズを使用するとパフォーマンスが向上することがあります。

TLB ミスは、Sun Performance Analyzer を使用して測定できます。

特定のプラットフォームでのデフォルトのページサイズは、Solaris OS コマンドの /usr/bin/pagesize を使用して取得できます。このコマンドで -a オプションを指定すると、サポートされるすべてのページサイズが表示されます。詳細は、pagesize(1) のマニュアルページを参照してください。

アプリケーションのデフォルトのページサイズを変更する方法は 3 つあります。