STREAMベンチマークは、単純な演算でのメモリデータのロード/ストア性能を測定するベンチマークテストです。STREAMは長い歴史を持ち歴代計算機のテスト結果が公開されているため比較が容易です。このテストを用いてXeon(R) (Nehalem) のメモリ性能を測定し結果を評価します。
STREAMには幾つかのテストがありますが、今回は "Triad" と呼ばれる "a(i) = b(i) + q*c(i)" の計算を行うテストを用いて性能評価します。
テストするデータサイズは200MBから搭載メモリを全て使うサイズまでを用います。利用するメモリサイズを増やして行くと、ローカルメモリからデータが溢れてリモートメモリが利用されまじめます。その場合にメモリ速度の違いが速度に反映されるはずです。
Xeon(R) (Nehalem) のメモリ性能やQPI性能を評価するためには、並列処理時のテストが大切です。そこで、OpenMPを用いた1, 2, 4, 8並列のSTREAM並列処理テストを行い、並列処理時のメモリ性能を確認します。
Xeon(R) (Nehalem) 世代から、メモリ構造が従来のSMP (Symmetric Multiprocessing) からNUMA (Non Uniform Memory Access) に変更されます。NUMAではCPUから見えるメモリがローカルメモリとリモートメモリに分割され、その接続経路の影響で性能差が現れます。
最新のLinux OSはメモリ割り当て制御を自動で最適に行えるようになっているようです。その効果を確認します。もし、十分な性能が得られるようならこの「OS任せ」が良い選択となります。しかし希望に反し、性能が良くないならば次に示す "numactl" コマンドを用いて手動でメモリ割当てを行う選択になります。しかし、マニュアル制御は神経を使うので可能な限り「OS任せ」を利用することをお勧めします。そのためにも解像度の高いテストが求められます。
2CPUにてメモリ割り当てを (OS任せ) にしたSTREAMベンチマーク
CPUやコアの指定は行っていない
メモリ割り当て制御も行っていない
OpenMP 1,2,4,8並列
OSによるローカルメモリとリモートメモリの最適化割り当てを利用する方法とは別に、Linuxではユーザがコマンドラインからメモリ割り当てのポリシーを指定できる"numactl"コマンドが用意されています。そこで、このコマンドを用いることで、ローカルメモリと、QPI経由で利用するリモートメモリの影響の度合いも調査してみたいと考えています。ただし、"numactl"コマンドを使用してアプリケーションを実行する場合は、ジョブスケジューラとの両立が難しくなりますので注意が必要です。
1CPUにてローカルメモリのみを使用したSTREAMベンチマーク
CPUはCPU-0のみを使用
メモリはMemory-Aのみを使用
ローカルメモリと呼ばれるメモリのみを使用
メモリへのアクセスはQPIの影響を受けない
ローカルメモリの純粋な性能を確認できる
OpenMP 1,2,4並列1CPUにてリモートメモリのみを使用したSTREAMベンチマーク
CPUはCPU-0のみを使用
メモリはMemory-Bのみを使用
リモートメモリと呼ばれるメモリのみを使用
メモリへのアクセスは常にQPIを介す制御なので純粋なQPIの影響を確認できる
OpenMP 1,2,4並列2CPUにてローカルメモリのみを使用したSTREAMベンチマーク
CPU-0、CPU-1の両方を使用
CPU-0で実行するスレッドはMemory-Aを使用する制御
CPU-1で実行するスレッドはMemory-Bを使用する制御
メモリを12GB以上使うあたりからQPIの影響が見える
OpenMP 1,2,4,8並列2CPUにてローカル/リモートメモリを均等に使用したSTREAMベンチマーク
CPU-A、CPU-Bの両方使用
メモリはリモート/ローカルを均等に使う
例:4GBのメモリを使う場合Memory-Aに2GB、Memory-Bに2GB確保
常にリモートメモリも使用するのでQPIの影響を受ける
OpenMP 1,2,4,8並列
HPC-ProServer DPeR610
CPU: X5570 2.93GHz
Memory: DDR3 1333MHz 24GB (4GB*6)
OS: CentOS5.3
Kernel 2.6.18-128.1.6.el5
Intel(R)C/C++ 11.0.083
グラフの横軸は使用するメモリの量を、グラフの縦軸は測定されたメモリバンド幅をあらわしています。
Xeon(R) (Nehalem) のメモリ構造を模式図にしました。今回の課題は、CPU-0を利用している時、CPUに直結されたMemory-Aを利用する場合のメモリ性能と、CPU-0からQPIを経由してMemory-Bを利用する場合、すなわちNUMA (Non Uniform Memory Access) 構造の影響を受けたメモリを利用する場合の性能の違いを詳しく確認することです。またその対策のヒントを得ることです。

日常的な「OS任せ」の動作、すなわちOSが自動的にコアのメモリ割り当てを行う場合の調査をSTREAMベンチマークテストで行いました。テストはOpenMPによる1, 2, 4, 8並列でのSTREAM Triadテストです。その結果以下のことがわかりました。
・ シリアル処理はローカルメモリに収まる12GB以下のサイズでは非常に高速
・ シリアル処理で12GBを越えてQPI経由のアクセスが始まっても十分に高速
・ さらに HPCで大切な、8並列処理は高性能が均一に出ている
・ (課題) 2並列や4並列では性能低下がみられる (要対策)

上のグラフでの赤色グラフ線の1スレッド処理に注目してください。データサイズが12GBよりも小さい領域では11510MB/secの性能です。ところが、12GBを越えると多少速度が低下します。これは12GBのローカルメモリ容量を越えたため、QPI経由でリモートメモリを利用する割合が増え始めたためです。使用量が増えるに従いすこしづつ性能が低下しています。しかし、心配された急激な性能低下には至っていません。「OS任せ」でも適切なメモリ割り当てコントロールが行われているようです。なお最大サイズでのメモリ速度は8650MB/sでした。
なおこの8650MB/sという性能は決して悪いものではないことを付記させてください。参考として以下に、STREAMベンチマークテストに公開されている結果から、1CPU機の歴代Top15のTriad性能を抜粋しました。さらにその表に今回確認された1スレッド処理での最高値11510MB/sと、最低値8650MB/sを追記しました。するとそれぞれが歴代10位と歴代13位に数えられる素晴らしい性能であることがわかります。
| 順位 | 計算機 | CPU数 | Triad (MB/s) |
| 1 | NEC_SX-5-16A | 1 | 47779 |
| 2 | Fujitsu_VPP5000 | 1 | 37544 |
| 3 | NEC_SX-7 | 1 | 35328 |
| 4 | NEC_SX-6 | 1 | 31983 |
| 5 | Cray_X1 | 1 | 24023 |
| 6 | NEC_SX-3-44 | 1 | 21972 |
| 7 | NEC_SX-4 | 1 | 15898 |
| 8 | Cray_T94 | 1 | 13920 |
| 9 | Cray_T932_321024-3E | 1 | 13682 |
| ☆ | Xeon (Nehalem) X5570 (1CPU-1thr, Local, OS任せ) | 1 | 11510 |
| 10 | Hitachi_S3600 | 1 | 10820 |
| 11 | NEC_SX-3-12 | 1 | 9713 |
| 12 | Cray_C90 | 1 | 9501 |
| ☆ | Xeon (Nehalem) X5570 (1CPU-1thr, Local+QPI, OS任せ) | 1 | 8650 |
| 13 | Core2DuoE8200_2GB_DDR3 | 1 | 7863 |
| 14 | AMD_Quad_FX_FX-72 | 1 | 7588 |
| 15 | HP_AlphaServer_GS1280-1300 | 1 | 7210 |
出典: STREAM (Sustainable Memory Bandwidth in High Performance Computers) に公開されている 「STREAM "standard" results」より1CPU機での歴代Top15によるTriadの値を抜粋。
青色のグラフ線で示した8スレッド処理の場合は、全てのサイズ領域で35GB/sの安定した性能を発揮しています。これはOSにより各コアが最適なローカルメモリを使用するよう正しく制御されていることの証です。実際のHPC利用では8並列処理が多いですから、その場合にはメモリ割り当てを「OS任せ」にしても安心です。
なおこの35585MB/sという性能は素晴らしい性能であることを付記させてください。参考として以下に、STREAMベンチマークテストで公開されている結果から、2CPU機の歴代Top15のTriad性能を抜粋しました。その表の中に今回確認された「OS任せ」での2CPU 8スレッドでの35585MB/sの値を挿入してみました。すると歴代4位に数えられる素晴らしい性能であることがわかりました。
| 順位 | 計算機 | CPU数 | Triad (MB/s) |
| 1 | NEC_SX-5-16A | 2 | 95328 |
| 2 | NEC_SX-7 | 2 | 70573 |
| 3 | NEC_SX-6 | 2 | 63909 |
| ◎ | Xeon (Nehalem) X5570 (1CPU-8thread, OS任せ) | 2 | 35585 |
| 4 | NEC_SX-4 | 2 | 31925 |
| 5 | Cray_T932_321024-3E | 2 | 26117 |
| 6 | Cray_C90 | 2 | 18246 |
| 7 | HP_AlphaServer_GS1280-1300 | 2 | 14376 |
| 8 | HP_AlphaServer_GS1280 | 2 | 12680 |
| 9 | HP_AlphaServer_ES47-1150 | 2 | 12638 |
| 10 | HP_AlphaServer_ES80-1150 | 2 | 12638 |
| 11 | HP_AlphaServer_ES47 | 2 | 10986 |
| 12 | HP_AlphaServer_ES80 | 2 | 10986 |
| 13 | HP_ProLiant_DL385 | 2 | 9721 |
| 14 | IBM_System_p5-520 | 2 | 9672 |
| 15 | HP_ProLiant_BL25p | 2 | 9499 |
出典: STREAM (Sustainable Memory Bandwidth in High Performance Computers) に公開されている 「STREAM "standard" results」より2CPU機での歴代Top15によるTriadを抜粋。
黄緑色と緑色のグラフ線で示した2/4スレッド処理の場合は、データサイズが小さな領域で性能が低下していることがわかりました。特に緑色で示した4スレッド処理での性能低下の範囲は広いため課題を残しています。しかし一般に、HPC計算を行う場合は1スレッド処理あるいは8スレッド並列処理が大勢を占めていますから、通常は「OS任せ」の利用で問題はありません。しかし、2/4スレッド処理が多い場合は対策が必要です。その具体策としては "numactl" コマンドの使用が考えられます。"numactl" コマンドを使用すると、強制的にコアに対して特定のメモリを割り当てることができますから、この問題を解消できます。
NUMAメモリの割り当てが「OS任せ」だと、Xeon(R) (Nehalem) のローカルメモリ性能とリモートメモリ性能を正確に測定できません。そこで "numactl" コマンドを用いて各コアに対するメモリ割り当てを手動操作で行い正確な性能測定を行います。
Xeon(R) (Nehalem) のローカルメモリ性能とQPI経由のリモートメモリ性能を正確に測定するるため、1CPUだけを利用してテストを行いました。使用したデバイスはCPU-0とMemory-Aです。
最初に1スレッドでメモリ性能を測定すると11565MB/sの性能でした。これは「OS任せ」が出した11510MB/sと同じ性能です。次に1CPU 4コアを用いた4スレッドのローカルメモリの性能を測定すると17910MB/sの性能でした。これは理論性能35GB/sの約半分の性能です。しかもこの性能は小さいなサイズから大きなサイズまで均一に出ています。

参考として以下に、STREAMベンチマークテストで公開されている結果から、1CPU機の歴代Top15のTriad性能を抜粋し、先に確認された1CPU 1スレッドでの11510MB/sと8650MB/sの値を表に挿入したものに、さらに1CPU 4コアで17910MB/sの値を追記しました。この性能は約10年前のベクトル計算機に並ぶメモリ性能です。
| 順位 | 計算機 | CPU数 | Triad (MB/s) |
| 1 | NEC_SX-5-16A | 1 | 47779 |
| 2 | Fujitsu_VPP5000 | 1 | 37544 |
| 3 | NEC_SX-7 | 1 | 35328 |
| 4 | NEC_SX-6 | 1 | 31983 |
| 5 | Cray_X1 | 1 | 24023 |
| 6 | NEC_SX-3-44 | 1 | 21972 |
| ☆ | Xeon (Nehalem) X5570 (1CPU-4thread, Local, numactl使用) | 1 | 17910 |
| 7 | NEC_SX-4 | 1 | 15898 |
| 8 | Cray_T94 | 1 | 13920 |
| 9 | Cray_T932_321024-3E | 1 | 13682 |
| ☆ | Xeon (Nehalem) X5570 (1CPU-1thread, Local, numactl使用) | 1 | 11565 |
| ☆ | Xeon (Nehalem) X5570 (1CPU-1thread, Local, OS任せ) | 1 | 11510 |
| 10 | Hitachi_S3600 | 1 | 10820 |
| 11 | NEC_SX-3-12 | 1 | 9713 |
| 12 | Cray_C90 | 1 | 9501 |
| ☆ | Xeon (Nehalem) X5570 (1CPU-1thread, Local+QPI, OS任せ) | 1 | 8650 |
| 13 | Core2DuoE8200_2GB_DDR3 | 1 | 7863 |
| 14 | AMD_Quad_FX_FX-72 | 1 | 7588 |
| 15 | HP_AlphaServer_GS1280-1300 | 1 | 7210 |
出典: STREAM (Sustainable Memory Bandwidth in High Performance Computers) に公開されている 「STREAM "standard" results」より1CPU機での歴代Top15によるTriadの値を抜粋。
次に"numactl" コマンドを使い、強制的にリモートメモリを使用するよう制御し1CPU 4コア機でSTREAMテストを行いました。使用したデバイスはCPU-0とMemory-Bです。
すると、1スレッド処理では7609MB/s、2スレッド処理では9012MB/s、4スレッド処理では9025MB/sの性能しか得られませんでした。先ほどのローカルメモリでの性能と比較すると約半分の性能しか出ていません。
この性能はXeon(R) (Nehalem) との比較では低く見えます。しかし、従来のXeon(R)と比較すると十分に高速です。また、このテストのようにリモートメモリのみを用いた極端な動作は現実には発生しないようです。通常は高速なローカルメモリが主に利用され、ローカルメモリが不足した場合にリモートメモリが部分的に利用されるような制御が行われます。そのため、実際にはこれほど極端な性能低下は発生しないと考えられます。

"numactl" コマンドにより2CPU 8コアでローカルメモリのみを使用するように指定したSTREAMテスト結果です。この「2CPU 8コアでローカルメモリのみを使用する指定」が "numactl" コマンドを利用する場合にお勧めしたい指定です。
赤色のグラフで示したシリアル処理は、冒頭で示した「OS任せ」のグラフとほぼ同じ性能を示しています。そして、12GBのローカルメモリを越えたサイズでの結果も同様の傾向です。(低速なリモートメモリの利用割合が増加するため、少しずつ性能低下。)
青色のグラフで示した8スレッド処理性能も、「OS任せ」の場合とほぼ同じ性能を示しています。この性能であれば特別に "numactl"コマンドを使用して性能向上を求める必要は見当たりません。
"numactl"コマンドが真価を発揮しそうな局面は、2/4スレッド処理の場合です。「OS任せ」の場合はこの処理での性能が大きく落ち込みますが "numactl"を利用するとその落ち込みは大きく改善されています。特に4スレッドでの性能改善は目覚しいものがあります。

"numactl" コマンドを用いて2CPU 8コアでのメモリ使用について、ローカルメモリとリモートメモリを均等に混合して利用するように指定したSTREAMテスト結果です。性能の出方は均質ですが、絶対性能は約2割前後の低下が確認できます。この指定は安定したパフォーマンスを求める用途には適していますが、HPCのように最高性能を求める用途にて不適当です。

Xeon(R) (Nehalem) のローカルメモリの速度は18GB/sと高速でが、QPI経由のリモートメモリの速度は9GMB/sと半分に低下しています。このNUMA (Non Uniform Memory Access) という名称にふさわしい性能の違いをどのように乗りこるかが課題です。
最新のLinux OSはNUMA構造を持つ計算機システムに対しても最適なメモリ割り当てを行えるような最適化がなされています。通常のHPC使用であればデフォルト構成でも問題ありません。
NUMA構造を持つ計算機のメモリ割り当てで、今回のテストで判明した2スレッド処理や4スレッド処理で起こったような現象が原因となり期待した性能が得られない場合は "numactl" コマンドの利用を検討する価値があります。しかし、"numactl" コマンドを利用する場合はジョブ投入時にコマンドラインからコアとメモリの組み合わせを指定する必要があるので注意が必要です。
AMD Opteron(TM) (Shanghai) のローカルメモリ性能とHT (HyperTransport (ハイパートランスポート)) 経由のリモートメモリ性能の確認も併せて行いました。
HPC-ProServer DPeM605 (Blade)
CPU: AMD Opteron(TM) 2384 2.70GHz
Memory: 16GB DDR2 667MHz
OS: CentOS 5.3 2.6.18-128.1.6.el5
Compiler : Intel(R) C++ 11.0.083
AMD Opteron(TM) (Shanghai) のシステム構造のブロック略図を作成しました。さらに比較のためXeon(R) (Nehalem) とXeon(R) (Core MA) のブロック図も掲載しました。図を見ると、AMD Opteron(TM) (Shanghai) と新Xeon(R) (Nehhlem) の双方共にNUMA構造を採用しています。CPU間通信の帯域も双方共に約25GB/sの性能を持たせています。ところが両者のメモリシステムは大きく異なっています。早期にリリースされたAMD Opteron(TM)はメモリシステムに2チャンネルのDDR2メモリシステムを採用し12.8GB/sのメモリ帯域を持つのに対して、後にリリースされたXeon(R) (Nehalem) は3チャンネルのDDR3メモリシステムを採用し最高で32GB/sのメモリ帯域を実現しています。STREAMEテストではこのメモリシステムの違いが結果として現れています。



テストの課題は、CPU-0のCore-0, 1, 2, 3を利用している時、CPU-0に直結されたMemory-Aを利用する場合のメモリ性能と、CPU-0からCPU間を接続するQPIを経由してMemory-Bを利用する場合、すなわちNUMA (Non Uniform Memory Access) 構造特有のメモリ性能の違いを詳しく確認します。
AMD Opteron(TM)のメモリ性能は素直に出ています。Xeon(R) (Nehalem) で課題であったような、データサイズが小さい領域での2スレッドと4スレッド処理での性能低下は発生していません。しかし、AMD Opteron(TM)の1/2/4スレッド処理性能と8スレッド処理性能の比は33%、45%、64%であるのに対して、Xeon(R)は31%、57%、75%と、2/4スレッドではXeon(R)が10%程度高速です。しかし、HPCでは8スレッド並列でシステムを利用することが多いので、この違いが問題になる場合は少ないと思われます。

"numactl" を用いてCPU-0とMemory-Aのみを使用し純粋なローカルメモリでのSTREAMテストを行いました。4スレッドの性能が伸び悩んでいます。メモリ性能不足です。

"numactl" を用いてCPU-0とMemory-Bのみを使用しHT (HyperTransport) 経由でのリモートメモリのみでのSTREAMテストを行いました。HT経由での処理オーバヘッドが少し見られます。また4スレッドでのメモリ性能不足も見られます。

AMD Opteron(TM) (Shanghai) は「OS任せ」の自動のメモリ割り当て機能が優秀で良い性能が出ているため、"numactl" を用いても更に性能が向上するようなことはありませんでした。

"numactl"を用いてローカルメモリとリモートメモリを均一に混合させて利用する指定です。1スレッドと8スレッドの性能は下がっていますが、逆に2スレッドと4スレッドの性能は速くなっています。

AMD Opteron(TM) (Shanghai) はSTREAMテストで素直な性能を示していました。