多数の CPU と大容量のメモリを必要とする構成では、ハードウエアに対する物理的な制限にぶつかることがあります。本章では、 CPU とメモリの間の通信帯域の制限が存在することによる制限事項について説明しています。また、このような問題に対応する目的で作られた、 Non-Uniform Memory Access (NUMA) と呼ばれるアーキテクチャ変更についても、説明を行っています。
NUMA 構成のハードウエアには複数のノードが存在しています。それぞれのノード内には、 CPU とメモリが存在しています。メモリへのアクセス速度は、 CPU に近い場所にあるのかどうかによって変化します。つまり全体的な処理性能も、アクセスすべきメモリが近い場所にあるのかどうかによって異なることになります。自動的な NUMA バランス調整の仕組みは、 CPU と CPU がアクセスすべきメモリを、できる限り CPU に近い位置に配置しようとする仕組みです。この仕組みを利用することで、 NUMA ハードウエアを使用していれば、劇的に性能を改善することができるようになります。
自動的な NUMA バランス調整は、下記の 3 つの手順で動作します:
タスクスキャナが定期的にタスクのアドレス領域の部分をスキャンし、次にアクセスする際に強制的にページフォルトを発生するようメモリにマークを設定します。
データへのアクセスが発生すると、 NUMA ヒンティングフォルトが発生します。このフォルトをベースにして、そのタスクと同じノード内にメモリを移行させるようにします。
タスクを維持するため、タスクが処理されている CPU とアクセスしようとしているメモリをグループ化して管理するようにします。
このような仕組みから、データのマップ解除とページフォルトが発生することになりますので、性能面のオーバーヘッドが生じることになります。しかしながら、一般的には性能向上によって十分に相殺されるはずです。
以前は NUMA ハードウエアで性能チューニングを行う場合、静的な設定を適用することが推奨されてきました。静的な設定を行う場合、メモリポリシーを numactl
, taskset
, cpusets
のいずれかで設定することができます。また、 NUMA に対応したアプリケーションの場合、 API を使用することもあります。静的な設定が既に作成されている場合は、アクセスすべきデータが既にローカルに存在していますので、自動的な NUMA バランス調整を無効化すべきです。
numactl
--hardware
を実行すると、マシン内のメモリ設定を表示することができるほか、 NUMA に対応しているかどうかも表示することができます。下記は 4 ノードのマシンでの出力例です。
>
numactl --hardware
available: 4 nodes (0-3)
node 0 cpus: 0 4 8 12 16 20 24 28 32 36 40 44
node 0 size: 16068 MB
node 0 free: 15909 MB
node 1 cpus: 1 5 9 13 17 21 25 29 33 37 41 45
node 1 size: 16157 MB
node 1 free: 15948 MB
node 2 cpus: 2 6 10 14 18 22 26 30 34 38 42 46
node 2 size: 16157 MB
node 2 free: 15981 MB
node 3 cpus: 3 7 11 15 19 23 27 31 35 39 43 47
node 3 size: 16157 MB
node 3 free: 16028 MB
node distances:
node 0 1 2 3
0: 10 20 20 20
1: 20 10 20 20
2: 20 20 10 20
3: 20 20 20 10
自動的な NUMA バランス調整を再起動するまでの間だけ有効化もしくは無効化したい場合は、 /proc/sys/kernel/numa_balancing
に 1
(有効化) もしくは 0
(無効化) を書き込んでください。恒久的に有効化もしくは無効化を行いたい場合は、カーネルのコマンドラインオプションで numa_balancing=[enable|disable]
[有効化|無効化] を指定してください。
自動的な NUMA バランス調整が有効化されている場合、タスクスキャナの動作を調整することができます。 タスクスキャナは、自動的な NUMA バランス調整によるオーバーヘッドと、それにかかる時間を考慮して、最適なデータ配置を判別します。
numa_balancing_scan_delay_ms
データをスキャンするまでに、スレッドが消費しなければならない CPU 時間を指定します。これにより、起動してすぐ終了してしまうようなプロセスを調整から除外することができます。
numa_balancing_scan_period_min_ms
および numa_balancing_scan_period_max_ms
タスクのデータをスキャンする頻度を制御します。フォルトの発生箇所によって、スキャン頻度は大きくも小さくもなります。これらの設定では、それぞれ最小値と最大値を設定します。
numa_balancing_scan_size_mb
タスクスキャナが有効化されている場合、どれだけの量のアドレス領域をスキャンするかを設定します。
最も重要な作業は、自動的な NUMA バランス調整を有効化した場合と無効化した場合で、その性能差を比較するために、お使いのサーバに対する性能基準を策定することです。 CPU 側に NUMA 関連の監視機能が付属していれば、メモリアクセスが近くに (ローカルに) あったものか、もしくは遠くに (リモートに) あったものかを監視するためのプロファイリングツールを使用することができます。自動的な NUMA バランス調整では、 /proc/vmstat
内の下記のパラメータで監視を行うことができます:
numa_pte_updates
NUMA ヒンティングフォルトでマークされたベースページの量を表します。
numa_huge_pte_updates
NUMA ヒンティングフォルトでマークされた、透過型巨大ページの量を表します。 numa_pte_updates
の値と組み合わせることで、マークされた全体のアドレス領域を計算することができます。
numa_hint_faults
どれだけの数に NUMA ヒンティングフォルトを捉えることができたのかを記録しています。
numa_hint_faults_local
ヒンティングフォルトのうち、どれだけがローカルのノードによるものであったのかを表します。 numa_hint_faults
の値と組み合わせることで、ローカルとリモートの割合を計算することができます。ローカルのノードによるものが大きければ大きいほど、多くの処理が単一ノード内に収束できていることがわかります。
numa_pages_migrated
配置がリモートであったために移行されたページ数を記録しています。移行処理ではコピー操作が行われるため、 NUMA バランス調整での最も大きなオーバーヘッドになります。
下記の出力例は、メモリポリシーまわりに特にチューニングを行っていない JVM の単一インスタンスを利用して、 SpecJBB 2005 を動作させた 4 ノードの NUMA マシンの様子を示しています。ただし、性能への影響は必ずしも良いものであるとは限りませんし、また下記の例は openSUSE Leap 12 のプレリリース版での例であることに注意してください。
Balancing disabled Balancing enabled TPut 1 26629.00 ( 0.00%) 26507.00 ( -0.46%) TPut 2 55841.00 ( 0.00%) 53592.00 ( -4.03%) TPut 3 86078.00 ( 0.00%) 86443.00 ( 0.42%) TPut 4 116764.00 ( 0.00%) 113272.00 ( -2.99%) TPut 5 143916.00 ( 0.00%) 141581.00 ( -1.62%) TPut 6 166854.00 ( 0.00%) 166706.00 ( -0.09%) TPut 7 195992.00 ( 0.00%) 192481.00 ( -1.79%) TPut 8 222045.00 ( 0.00%) 227143.00 ( 2.30%) TPut 9 248872.00 ( 0.00%) 250123.00 ( 0.50%) TPut 10 270934.00 ( 0.00%) 279314.00 ( 3.09%) TPut 11 297217.00 ( 0.00%) 301878.00 ( 1.57%) TPut 12 311021.00 ( 0.00%) 326048.00 ( 4.83%) TPut 13 324145.00 ( 0.00%) 346855.00 ( 7.01%) TPut 14 345973.00 ( 0.00%) 378741.00 ( 9.47%) TPut 15 354199.00 ( 0.00%) 394268.00 ( 11.31%) TPut 16 378016.00 ( 0.00%) 426782.00 ( 12.90%) TPut 17 392553.00 ( 0.00%) 437772.00 ( 11.52%) TPut 18 396630.00 ( 0.00%) 456715.00 ( 15.15%) TPut 19 399114.00 ( 0.00%) 484020.00 ( 21.27%) TPut 20 413907.00 ( 0.00%) 493618.00 ( 19.26%) TPut 21 413173.00 ( 0.00%) 510386.00 ( 23.53%) TPut 22 420256.00 ( 0.00%) 521016.00 ( 23.98%) TPut 23 425581.00 ( 0.00%) 536214.00 ( 26.00%) TPut 24 429052.00 ( 0.00%) 532469.00 ( 24.10%) TPut 25 426127.00 ( 0.00%) 526548.00 ( 23.57%) TPut 26 422428.00 ( 0.00%) 531994.00 ( 25.94%) TPut 27 424378.00 ( 0.00%) 488340.00 ( 15.07%) TPut 28 419338.00 ( 0.00%) 543016.00 ( 29.49%) TPut 29 403347.00 ( 0.00%) 529178.00 ( 31.20%) TPut 30 408681.00 ( 0.00%) 510621.00 ( 24.94%) TPut 31 406496.00 ( 0.00%) 499781.00 ( 22.95%) TPut 32 404931.00 ( 0.00%) 502313.00 ( 24.05%) TPut 33 397353.00 ( 0.00%) 522418.00 ( 31.47%) TPut 34 382271.00 ( 0.00%) 491989.00 ( 28.70%) TPut 35 388965.00 ( 0.00%) 493012.00 ( 26.75%) TPut 36 374702.00 ( 0.00%) 502677.00 ( 34.15%) TPut 37 367578.00 ( 0.00%) 500588.00 ( 36.19%) TPut 38 367121.00 ( 0.00%) 496977.00 ( 35.37%) TPut 39 355956.00 ( 0.00%) 489430.00 ( 37.50%) TPut 40 350855.00 ( 0.00%) 487802.00 ( 39.03%) TPut 41 345001.00 ( 0.00%) 468021.00 ( 35.66%) TPut 42 336177.00 ( 0.00%) 462260.00 ( 37.50%) TPut 43 329169.00 ( 0.00%) 467906.00 ( 42.15%) TPut 44 329475.00 ( 0.00%) 470784.00 ( 42.89%) TPut 45 323845.00 ( 0.00%) 450739.00 ( 39.18%) TPut 46 323878.00 ( 0.00%) 435457.00 ( 34.45%) TPut 47 310524.00 ( 0.00%) 403914.00 ( 30.07%) TPut 48 311843.00 ( 0.00%) 459017.00 ( 47.19%) Balancing Disabled Balancing Enabled Expctd Warehouse 48.00 ( 0.00%) 48.00 ( 0.00%) Expctd Peak Bops 310524.00 ( 0.00%) 403914.00 ( 30.07%) Actual Warehouse 25.00 ( 0.00%) 29.00 ( 16.00%) Actual Peak Bops 429052.00 ( 0.00%) 543016.00 ( 26.56%) SpecJBB Bops 6364.00 ( 0.00%) 9368.00 ( 47.20%) SpecJBB Bops/JVM 6364.00 ( 0.00%) 9368.00 ( 47.20%)
自動的な NUMA バランス調整の仕組みにより、 NUMA マシンで高性能なチューニングを行う際、それにかかる手間を減らすことができます。とはいえ、可能であれば各ノード内で負荷を分割できるような静的なチューニングを行っておく必要はあります。しかしながら、ほとんどの場合において NUMA バランス調整は性能改善の効果があります。