新型Opteronプロセッサ (以下、Interlagos (開発コード)) を導入されるお客様が増えています。Interlagosの特徴は、プロセッサのメニーコア化を促進するため、Multi Chip Module (以下、MCM) と呼ばれる、プロセッサの中に2個のCPUダイを搭載し、このCPUダイの中には8個のコアが搭載されていて、全体では16コアのメニーコア・プロセッサを実現していることです。次の図はその仕組みを示したものです。
なおこのアーキテクチャ全体の呼称は "Bulldoser" アーキテクチャ、CPUダイの呼称は "Bulldozer die"、コアの呼称は "Bulldozer core" です。
・ 8個のコアを搭載するCPUダイを2個搭載することで、16コアのメニーコアプロセッサを実現
・ 各CPUダイは2本のメモリチャンネルを持ち、25.6GB/sのメモリ帯域を実現
・ 各プロセッサは4本メモリチャネルを持ち、51.2GB/sのメモリ帯域を実現 (25.6 x2)
・ プロセッサ内部のCPUダイ間は高速な通信デバイスで接続
・ 最大4個のプロセッサを高速な通信デバイスで接続でき64コア機を実現
Interlagosのメモリシステムは下の図のように3階層で構成されているので注意が必要です。
・ 1番目の階層、CPUダイ上のコア群、対称型メモリ共有 (高速)
・ 2番目の階層、プロセッサ上のCPUダイ群、非対称型メモリ共有 (中速)
・ 3番目の階層、マザーボード上のプロセッサ群、非対称型メモリ共有 (中速)
・ (4番目の階層、クラスタ上の計算機群、分散型メモリ (中速))

Interlagosは普通の情報処理用途なら高いスループットが期待できるプロセッサです。しかしHPC用途では、上の図で示したような複雑な内部構造を持つため、ボトルネックの発生に注意した利用が必要です。そこでこのページでは「Interlagosのメモリ帯域を使い尽くす」ことを目指し、ボトルネックが発生する場所を明らかにするベンチマークテストを実施します。
システムに搭載されてるメモリ管理用のコマンドに "distance" というオプションを付けると、CPUダイとメモリの関の理論距離を詳しく表示させることができます。そこでこのコマンドを使って8個のCPUダイと8個のメモリとの理論距離を表示させ、その結果を表にしました。行はCPUダイを、列はメモリを表します。
表を見ると、CPUダイとメモリとの理論距離を確認することができます。
・ CPUダイdie00と、同プロセッサ上の、同CPUダイdie00に接続のメモリm00との理論距離は 10
・ CPUダイdie00と、同プロセッサ上の、異CPUダイdie01に接続のメモリm01との理論距離は 16
・ CPUダイdie00と、異プロセッサ上の、異CPUダイdie10に接続のメモリm10との理論距離は 16
・ CPUダイdie00と、異プロセッサ上の、異CPUダイdie11に接続のメモリm11との理論距離は 22
さらに理論距離は次のような要素に分解できることがわかります。これを通信経路に応じて加算することで理論距離を計算しているようです。
・ CPUダイとメモリとの間の理論距離は 10
・ CPUダイとCPUダイとの間の理論距離は 6
・ プロセッサとプロセッサとの間の理論距離は 6
・ プロセッサ上の2個のダイは、一方は外部との接続ポートがあるが、他方は外部との接続ポートがない
| CPUダイとメモリとの理論距離 (die00とm00との距離を10とした場合の理論距離) | ||||||||
| メモリ | ||||||||
| CPUダイ | m00 | m01 | m10 | m11 | m20 | m21 | m30 | m31 |
| die00 | 10 | 16 | 16 | 22 | 16 | 22 | 16 | 22 |
| die01 | 16 | 10 | 22 | 16 | 16 | 22 | 22 | 16 |
| die10 | 16 | 22 | 10 | 16 | 16 | 16 | 16 | 16 |
| die11 | 22 | 16 | 16 | 10 | 16 | 16 | 22 | 22 |
| die20 | 16 | 16 | 16 | 16 | 10 | 16 | 16 | 22 |
| die21 | 22 | 22 | 16 | 16 | 16 | 10 | 22 | 16 |
| die30 | 16 | 22 | 16 | 22 | 16 | 22 | 10 | 16 |
| die31 | 22 | 16 | 16 | 22 | 22 | 16 | 16 | 10 |

MCMを採用したプロセッサには2つの問題が考えられます。
1番目の問題は、CPUダイが利用できるメモリ帯域が25.6GB/sと狭いため、メモリ性能律速型アプリケーションを動作させるとメモリボトルネックが発生するかもしれないということです。
しかしこの問題は発生しないことがわかっています。これは過去にSPECfp 2006の結果を調べていて判りました。任意のCPUダイにメモリ性能律速型アプリケーションを投入しても、1ジョブを投入するだけならメモリ帯域を使いきることはありません。メモリ帯域を使い切るためには2ジョブ以上を投入しなければならないのです。
1番目の問題の解決はこの特性を利用します。具体的には、全てのCPUダイとローカルメモリをセットにしておきます。そこにジョブを順番に1ジョブづつ投入すればメモリボトルネックを発生させることなくジョブをじっこうできます。全てのCPUダイとローカルメモリのセットに1ジョブづづを投入し終えたら、再び初めのセットに戻り、そこから2回目のジョブ投入を行います。2回目のジョブ投入が終わったら、また最初のセットから繰り返します。このジョブ投入を全てのコアを使いきるまで繰り返します。
もちろんジョブ投入を続けていくうちに、メモリ帯域を使い尽くすことになります。しかしこのような方法でメモリ帯域を使い尽くせば、システムのメモリ帯域を余すことなく使い尽くしたことになります。なお、メモリ帯域を使い尽くした時点でジョブ投入を停止させることができれば理想的です。
第2の問題は、ジョブをシステムに単純に投入すると、使用するCPUダイとメモリの距離が離れることがあり、メモリボトルネックが発生して性能が低下するため発生する問題です。
第2の問題は次のようにすれば解決できます。システムにジョブを投入する時、CPUダイとローカルメモリを固定してジョブ投入できます。このようなジョブ投入を実施すると常に高速なメモリを使うことができ性能が低下しません。
なお、この2つの問題を同時に解決するためには、ジョブスケジューラを利用したジョブ投入が簡単で便利です。
ジョブスケジューラを使うなどの方法でCPUダイとローカルメモリを固定し、全てのメモリ帯域を無駄なく使えることがわかりました。ではもし仮にCPUダイとメモリの関係を適切に管理できなければ、どのような問題が発生するのでしょうか。それを確認するためのテストを行いました。
テストに用いたベンチマークテストは計算機のメモリ帯域測定用のプログラムとして有名な "stream" です。このベンチマークテストによってCPUダイとメモリの組み合わせを変更した場合のメモリ帯域の変化を調べています。
測定に用いた計算機の構成は次のような構成です。
Server: HPC-ProServer DPe R815 (BIOS-2.3.0)
OS: ScientificLinux 6.1 Kernel-2.6.32-131.21.1.el6.x86_64
CPU: Opteron 6276 (Interlagos) 16-core 4CPU total 64-core
Memory: DDR3 1600MHz, 4GBx16: 64GB
Compiler: IntelCompiler 12.1.1.256
Library: glibc glibc-2.12-1.47.el6.x86_64
CPUダイを固定し、8系統に分散されたメモリを順に接続した場合の、CPUダイと各メモリでのメモリ帯域を測定しました。具体的には、使用するCPUダイを "cpubind" コマンドによってdie00に固定し、利用するメモリも "memorybind" コマンドによってm00からm31まで順に固定し、それぞれのセットについてstreamベンチマークテストを実施しました。データサイズは1GB、スレッド数は4です。その結果を次の表にしました。
| CPUダイdie00と 次の各メモリとの転送性能 (GB/s) |
|||||||||
| m00 | m01 | m10 | m11 | m20 | m21 | m30 | m31 | ||
| stream | Copy | 16.6 | 7.3 | 5.6 | 3.8 | 5.3 | 3.7 | 5.5 | 4.0 |
| Scale | 17.5 | 7.3 | 5.4 | 3.8 | 5.3 | 3.7 | 5.5 | 4.0 | |
| Add | 16.2 | 6.7 | 5.5 | 4.9 | 4.4 | 4.2 | 4.4 | 3.0 | |
| Triad | 16.1 | 6.7 | 5.5 | 4.9 | 4.4 | 4.2 | 4.4 | 3.0 | |
die00とm00との理論距離を10とした場合の |
理論距離 | 10 | 16 | 16 | 22 | 16 | 22 | 16 | 22 |
| 実測距離 | 10 | 22 | 32 | 44 | 32 | 44 | 32 | 44 | |
CPUダイdie00と各メモリとの理論距離は次のようになります。
・ 通信回数が0回の時のCPUダイdie00とローカルメモリとの理論距離 10
・ 通信回数が1回の時のCPUダイdie00とリモートメモリとの理論距離 16
・ 通信回数が2回の時のCPUダイdie00とリモートメモリとの理論距離 22
ところが実際のテスト結果を見ると、実メモリ帯域は理論距離の比よりも大幅に低いことがわかりました。その全体像を掴むためstreamテストの結果をグラフ化しました。さらに比較のため幾つかのデータを追加し次の6種類のデータのグラフを作成しました。
| ・ 理論距離 (distance) | "distance" オプションで表示されたCPUダイと各メモリとの理論距離 (メモリ帯域に換算) |
| ・ 理論距離 (distance)を2倍 (参考) | "distance" で表示された値を2倍にしたもの (実際のメモリ帯域に近い) |
| ・ stream copy | "stream"ベンチで得られた "copy" の値 |
| ・ stream add | "stream"ベンチで得られた "add" の値 |
| ・ メモリ理論性能 | DDR3 1600 x2メモリの理論性能25.6GB/s |
| ・ PCIe2.0 x8理論性能 | PCIe2.0 x8の理論性能4GB/s (計算機間通信の帯域との比較用、実効値は2GB/s程度) |
なおこのグラフでは、理論距離とメモリ帯域の単位を統一するため、理論距離の値10を、ローカルメモリの "copy" の実効性能である16.6GB/sで置き換え、残りの理論距離もこれに比例させた値を使っています。
また理論距離の値を2倍にすると "copy" のグラフとピタリと重なることがわかりました。そこで、理論距離の値を2倍したグラフも「理論距離 (diatance) を2倍 (参考)」として追記しました。

Interlagosは、CPUダイとローカルメモリ間のメモリ帯域は高速です。ところがリモートメモリの性能はローカルメモリの性能の1/3以下しかありません。そのためリモートメモリを使ってメモリ性能律速型アプリケーションを動作させるとメモリボトルネックが発生します。InterlagosはCPUダイとローカルメモリをセットで動作させなければなりません。
またPCIe2.0 x8の理論性能を示したグラフも追記しました。PCIe2.0 x8の理論性能は4GB/s、ネットワーク並列で利用するInfiniBandでの実効性能は約2GB/sです。
このグラフを見ると、計算機システムの通信速度は次の2つに大別されることがよくわかります。
・ 高速通信グループ:CPUダイの内部の通信グループ
・ 中速通信グルーブ:CPUダイ間、プロセッサ間、システム間の通信グループ
Interlagosを用いて並列計算をする場合は、この両者の通信速度の違いを考慮したジョブ投入が必要です。
Interlagosの内部構造をstreamベンチの結果を元にして模式図にしました。青色で示したCPUダイdie00からメモリm00, m01, m10, m11, m20, m21, m30, m31との実測距離を青字で示した模式図です。
この図をみるとInterlagosのリモートメモリは使いものにならないことがよくわかります。Interlagosを使うならローカルメモリを使うべきです。

そこで次に、各CPUダイから各ローカルメモリまでの距離を個々に示した模式図を作りました。この図を見ると、Interlagos4ソケット機は、実際は8ソケットのネットワーク並列機として利用した方が良いことがわかります。

この図を元にして、Interlagosに適した計算と、適さない計算を考えました。それを次に示します。
Interlagosに適した計算
・ メモリ性能律速型アプリケーション、平行処理スループットを必要とする計算
・ メモリ性能律速型アプリケーション、並列処理オーバーヘッドが小さく並列処理性能を必要とする計算・ CPU性能律速型アプリケーション、平行処理スループットを必要とする計算
・ CPU性能律速型アプリケーション、並列処理オーバーヘッドが小さく並列処理性能を必要とする計算
Interlagosに適さない計算
・ メモリ性能律速型アプリケーション、高速なシリアル処理性能を必要とする計算
・ メモリ性能律速型アプリケーション、並列処理オーバーヘッドが大きく並列処理性能を必要とする計算・ CPU性能律速型アプリケーション、高速なシリアル処理性能を必要とする計算
・ CPU性能律速型アプリケーション、並列処理オーバーヘッドが大きく並列処理性能を必要とする計算
これまでは4ソケット機全体をテストしていました。そこで次は一個のCPUダイに絞って、そこでのローカルメモリの性能を調べました。

テストの方法は、プロセッサp0に搭載されているCPUダイdie00上の、コアc000, c001, c002, c003, c004, c005, c006, c007とローカルメモリm00を使い、スレッド数を1, 2, 4, 8と変化させstreamによってメモリ帯域を測定しました。
| CPUダイdie00と メモリm00との間のメモリ帯域 (GB/s) |
|||||
| # of threads | 1 | 2 | 4 | 8 | |
| stream (GB/s) |
Copy | 11.0 | 15.2 | 16.8 | 16.6 |
| Scale | 9.7 | 15.1 | 17.7 | 16.7 | |
| Add | 9.8 | 14.2 | 16.4 | 15.3 | |
| Triad | 9.9 | 14.1 | 16.3 | 15.3 | |
テストによって次のことがわかりました。
・ 1スレッド処理で実効メモリ帯域の約70パーセントを消費する
・ 2スレッド処理で実効メモリ帯域を全て使う、メモリボトルネックが発生している
・ 4スレッド処理で最大実効メモリ帯域に到達、しかし大きなメモリ帯域不足
・ 8スレッド処理でメモリ帯域が低下し始めた
この文書の冒頭でも述べていますが、SPECfp 2006の調査結果では、メモリ性能律速型アプリケーションのシリアル処理ではメモリ帯域が余り、2平行処理を超えるたところでメモリ帯域を使い切っていると報告しました。
これはstreamによるベンチマークテスト結果とも一致しています。ただし、streamの計算は非常に単純なため。最も激しくメモリ帯域を使います。そのためstreamは2平行処理でメモリ帯域を使いきっています。
次は4ソケット機全体のメモリ帯域を調査します。システムには64個のコアが搭載されています。しかし先ほどのテストの結果から、メモリ帯域のピーク性能はCPUダイあたり4スレッド処理で得られることがわかりました。そこでこのテストでは各CPUダイに4スレッド処理を割り当て、全体で32スレッド処理となるようにジョブ投入し、最大性能を記録することを目指しました。そのテストの結果を次に示します。
| CPUダイdie00, die01, die10, die11, die20, die21, die30, die31と メモリmm00, mm01, mm10, mm11, mm20, mm21, mm30, mm31との間のメモリ帯域 (GB/s) |
1個のCPUダイ での結果を 4倍した値 (参考) |
||
| # of threads | 32 | 32 | |
| stream (GB/s) |
Copy | 117.0 | 134.4 |
| Scale | 117.0 | 137.4 | |
| Add | 108.6 | 131.2 | |
| Triad | 108.4 | 130.4 | |
この結果を見ると、単独のプロセッサの性能よりも、4個のプロセッサを平行動作させた時のメモリ帯域の方が20%近くも狭いことがわかりました。4個のプロセッサ全体を同時に動作させると、通信のコリジョンが発生するようです。
Interlagos2ソケット機とXeon2ソケット機の総メモリ帯域の比較です。手元にあった過去のXeon X5570 2ソケット機によるデータと、先ほどの4ソケットのIntelagosでのメモリ帯域を半分にした値を比較しています。Interlagosのメモリ帯域はXeonよりも1.5倍も広帯域です。Intelagosはメモリ性能律速型アプリケーションにとって優れたプラットホームです。
| Xeon X5570 x2 (2p 8c) |
Opteron 6276 x2 (2p 32c) | ||
| ダイとメモリ | p0, p1 mm00, mm10 |
die00, die01, die10, die11 mm00, mm01, mm10, mm11 |
|
| # of threads | 8 | 16 | |
| stream (GB/s) |
Copy | 38.0 | 58.5 |
| Scale | 38.6 | 58.5 | |
| Add | 36.6 | 54.3 | |
| Triad | 37.9 | 54.3 | |
| 理論性能 (GB/s) |
64.0 (10.66 x6) |
102.4 (12.8 x8) |
|
計算機環境: Xeon
Server: DPeR410 (Firmware 1.1.5)
CPU : Xeon X5570 x 2
Memory : DDR3-1333 4GB reg x 6
OS : CentOS 5u3 x86-64 kernel 2.6.18-164
Compiler Intel 11.0 083
V.S.
計算機環境: Opteron
Server: HPC-ProServer DPe R815 (BIOS-2.3.0)
OS: ScientificLinux 6.1 Kernel-2.6.32-131.21.1.el6.x86_64
CPU: Opteron 6276 (Interlagos) 16-core 4CPU total 64-core
Memory: DDR3 1600MHz, 4GBx16: 64GB
Compiler: IntelCompiler 12.1.1.256
Library: glibc glibc-2.12-1.47.el6.x86_64
数年前の計算機はコア数とメモリ容量が共に少なくシステム構造が単純なシステムでした。そのためジョブスケジューラによる資源管理は「資源の公平な配分」を実現するだけで充分でした。
・ 計算機の無駄の最小化、コアやメモリの空きを把握し無駄のないジョブ投入
・ 並列処理効率の向上を目指した資源管理とジョブ管理
・ ソフトウェアライセンスなどの二次的リソースにも配慮したジョブ管理
・ 決められたルールに則った公平なジョブ管理
ところが、プロセッサのメニーコア化とメモリシステムの分散化などによって、計算機の構造が複雑化すると、ジョブスケジューラには一段と高度な管理が求められるようになってきました。
・ スレッド並列とプロセス並列を組み合わせた階層型並列処理に対応したジョブ管理
・ 個々のアプリケーションの各CPUダイでの最適な並列度を考慮したジョブ投入
・ 使用するCPUダイとローカルメモリのセットを固定化したジョブ投入
CPUダイのメニーコア化によってプロセッサの性能向上は加速度的に進みます。またメモリ容量も加速度的に増加します。しかし一方で、CPUダイ間の通信性能、プロセッサ間の通信性能、計算機間の通信性能など、並列処理で欠かせない各階層の通信性能は直線的にしか向上しません。そのため、両者の性能の乖離は今後ますます増大すると考えられます。
この課題に対処するため、階層的な並列処理の実施は不可欠になっています。CPUダイの内部の並列処理はOpenMP (数値演算ライブラリ) を利用したスレッド並列を使い、多数のCPUダイを利用した並列計算はOpenMPIを利用したプロセス並列を使うという、階層型の並列処理の利用です。
これと併せて階層的な並列処理に対応したジョブ管理システムの利用も大切です。ジョブ管理に無頓着だと計算機の性能向上の恩恵を受けられなくなる可能性があります。