LinuxCon Japan 2012を3倍楽しむための基礎知識

第5回 Linux Kernelメモリ管理最新動向[その1]

この記事を読むのに必要な時間:およそ 3.5 分

2012年6月6日~8日にLinuxCon Japan 2012が開催されます。ここではLinux Kernelの最新技術の発表や議論がいろいろ行われるのですが,カンファレンスを楽しむ手助けとなる記事を…ということで,最近のLinux Kernelのメモリ管理の以下のトピックについて,2回に分けて紹介したいと思います。

今回は,

  • NUMA対応
  • 組込みシステム向けの新機能

次回は

  • ファイルシステム,デバイスと連携したエンハンス
  • メモリ資源管理機能(cgroup)
  • CleanCache

を取り上げます。

それぞれ,LKMLでどのような提案があって,提案の理由は何か? 現在はどうなっているのか? ということを簡単に紹介したいと思います。

NUMA対応

性能エンハンス機能として現在議論されているのが,NUMAマシン上のアプリケーションのチューニング機能です。現在,全く別の方式が有名ハッカー2人から提案されていることもあり,この議論は注目されています。

まず,NUMA(Non Uniformed Memory Architecture)とは何かをおさらいします。

NUMAとは,CPUがメモリアクセスをする際に,アクセス対象メモリの物理的な位置に依存してアクセスコストが変わるアーキテクチャです。たとえば,最近のx86 系CPUではCPU内にMMU(Memory Management Unit)が内蔵されており,CPUから直接DIMMに接続する形になっています。複数CPUがある場合,あるCPUに繋がったDIMMに別のCPUからもアクセスはできますが,この場合は自分に直接繋がっているDIMMへのアクセスよりもアクセスのコストが高くなります。つまり,CPUとDIMMの距離でアクセスコストが変わることになります。図1にその概要を示します。

図1 NUMAにおける Threadの動作するCPUとメモリの距離の違いによる性能差

図1 NUMAにおける Threadの動作するCPUとメモリの距離の違いによる性能差

NUMAの場合,ファームウェアからカーネルに,CPUとメモリの距離を教えてくれる仕組みがありますので,それを参照しつつ,カーネルは 近い距離にあるCPUとメモリをまとめ,Nodeと呼ばれるCPUとメモリの組を作ります。threadが走行しているCPUと同じNodeのメモリを使っている場合,メモリアクセスコストが抑えられ,効率の良い動作になります。

【備考】
NIC等のデバイスとCPU,メモリの間にも距離の概念はあって,同じようなことが言えます。

現在の実装

現在のLinuxの実装では,threadがメモリを要求した際は,現在threadが走行中のCPUが所属するNodeからメモリ獲得を行うようになっています。このため,短時間で実行が終了するアプリケーションは大体最適なメモリ配置で動作します。ところが長時間動作するアプリケーションの場合,スケジューラの都合でthreadの走行するCPUを別のNodeに移動されてしまうことがあります。そうすると,元々メモリを獲得したNodeと移動先CPUの位置関係が遠くなるため,メモリアクセスコストが上昇してしまいます。

これは,スケジューラはthreadがどのNodeのメモリを主に使っているかを意識しない実装になっているからです。このため,長時間動作するアプリケーションの場合は,ユーザ側が使用するNodeを固定する等のチューニングを行わないと性能が出にくいことがあります。

従来,性能を重視するアプリケーションは,CPU位置やメモリ位置を指定するシステムコールや,cgroupのcpuset等で自身を特定のNodeにくくりつけることによりNUMAに対応してきました。この方法は,良い性能が出るのはいいのですが,ユーザにくくりつけをさせるので,ユーザがハードウェア構成を理解し,CPUメモリ配分を見切ってアプリケーションとNodeの関係を調整する必要があります。使用するアプリ/ハード構成にあわせて細かいチューニングも必要になり,総じて非NUMAマシンよりも扱いにくくなっているのですが,ここをなんとかしないと性能は出ません。最近はNUMAマシンが増えてきましたので,ハード性能を十分に引き出すための,簡単かつ動的なチューニング方法が求められています。

メモリの開発者達にとってもこれは大きな課題になっていて,議論がされています。これから紹介する2つの提案は,ユーザ側で細かいチューニング・配分などしなくても,ある程度はカーネルにお任せで性能が出るようにしよう,という提案です。1つはPeter Zijlstra氏(Red Hat)から,もう1つは Andrea Arcangeli氏(Red Hat)からの提案です。どちらもアプリケーションが細かくNode位置を意識しなくても自動的にメモリを最適に配置する機能なのですが,それぞれ考え方が異なります。

SchedNUMA

Peter氏の提案はschedNUMAという名前で,いくつかの機能が盛り込まれています。

1つ目は,一度獲得したメモリを「次のアクセスがあったNode」に移動(マイグレーション)するLazy Migration機能です。従来は,ユーザが移動先や固定先を具体的に指示し,使いたいNodeをあらかじめ指示する必要がありましたが,この指定方法は「具体的にはどのNodeか判らないけれども,とりあえずメモリアクセスのあったCPUのNodeに移動する」という指定方式で,ユーザが頑張ってthread配置を見切らなくても必要なページを必要な個所に配置できます。

2つ目は,threadに対して Home Nodeという概念を導入し,できる限りHome Node内でスケジューリングを行い,CPUとメモリの関係を崩さないようにする機能です。threadがHomeNodeを持つ場合,threadは可能な限りHomeNode内のCPUで走行するようにスケジュールします。例えば,一時的に他のNodeに移動してしまってもHome Nodeに戻ってこれるようにします。また,メモリ獲得時には「今threadが走行しているNode」からではなく,Home Nodeからメモリ獲得を行うようにします。これにより,一時的なthreadのNode間移動によってメモリ配置がバラバラになってしまうを現象を排除します。

3つ目は,Home node migrationという仕組みを導入し,threadがどうしてもHome Nodeを離れなければならない場合,threadのCPU移動と同時にメモリ内容も移動させる機能です(前述のLazy Migrationを使います)。

これら3つの機能によってスケジューラがthreadとNodeの関係を意識して動作するようにしつつ,メモリ側もスケジューラの意思決定に追従できるようにしています。

最後に,アプリケーションからschedNUMAを使用するための新システムコールをいくつか追加しています。Numa groupという概念を導入し,numa_tbind()/numa_mbind()というシステムコールによって,threadやメモリをNuma groupに関連付けできるようにします。Numa groupというのは「同じNodeに集めるべきスレッドやメモリの組」であり,Numa group内のthreadがNodeを超えてマイグレーションする場合,同じNuma groupに所属するスレッド・メモリをまとめて移動させます。

このNuma groupにより,アプリケーションは,具体的に「Node AのCPU-BにスレッドXを配置!」「メモリYY~ZZはNode Aに配置!」と伝えるのではなく,「どこでもいいけど同じNuma groupのスレッドとメモリはお互いに近いところに配置してね…」とカーネルに伝えることができるようになります。アプリケーションが Home Nodeに納まらない場合,つまり,アプリケーションが複数Nodeにまたがるような巨大なものである場合,アプリケーションの部位ごとに前述のシステムコールで細かく指定することになりますが,この辺りは研究の余地があるかもしれません。

※)
名前が似ていますがcgroupとは関係ありません。

AutoNUMA

Andrea氏が提案しているのはAutoNUMAという機能です。システムコールは追加せず,カーネル側でアプリケーションの挙動を解析し,自動的に最適なメモリ配置を行うというものになっています(この動作は彼が開発したTransparent Huge page に似ていますね)。まず,ページテーブルに細工をし,アプリケーションのメモリアクセスを記録します。その情報を用いて頻繁にリモートメモリにアクセスしている部分を見つけ出し,カーネルスレッドで巡回しながら自動的にメモリを再配置するほか,スケジューラがタスクを移動する際のヒントとしても使います。Peter氏のものと比較して,全自動なのでアプリケーション側の対応がいらなくなりますが,メモリアクセスの記録コストやカーネルスレッドによる巡回コストが大きな問題となっています。

2人ともRed Hat所属なのですが,それぞれ別々の方法を提案し,LKML上で激しく議論をしているのが面白いところです。このオープンさがコミュニティ開発らしいですよね。Peterの方はアプリケーションの修正が必要になりますし,Andrea氏の方はリソースをかなり使いますので,お互いのいいところをマージするような形になるといいですね。

著者プロフィール

亀澤寛之(かめざわひろゆき)

静岡県在住のLinuxエンジニアです。現在,memory cgroupのメンテナの一人をつとめており,主にメモリ関連の話題に口を出しています。富士通株式会社のLinuxエンジニアの一人としてサーバシステムの開発やサポートに従事しています。

コメント

コメントの記入