Skip to content
Published on

CXLメモリティアリング、カーネルはどこまで来たか — DAMONがマージしたものと数字が測っていないもの

シェア
Authors

はじめに — CXLの話の中でカーネルが担う部分

CXLハードウェアの話は、退役したDDR4を蘇らせるMetaのCXLブリッジチップの回で一度扱いました。退役したDDR4をCXLで蘇らせ、第二のメモリ階層として使うという、ハイパースケールの実戦配備報告でした。

しかし、チップが挿さっていることと、それが値を出すことは別の話です。CXLメモリはオペレーティングシステムから見ればCPUを持たないNUMAノードにすぎず、どのページが熱くどのページが冷めているかを判断し、実際に動かす作業はすべてカーネルが担います。この判断を誤れば、CXLはただの遅いRAMです。

そこで本稿は、ハードウェアではなくその上で動くコードを見ます。2026年7月現在のLinux mainlineに実際に何が入っているのかをカーネルソースで直接確認し、この分野で引用される数字が元の出典において正確に何を測り何を測っていないのかを追います。結論を先に言えば、入ったのは部品であり、方針はまだあなた次第で、数字は大きいほど付随する方法論が少ない傾向にあります。

カーネルがページを動かす2つの方法

まず地形から。ティアリングされたメモリでページを動かすmainlineのメカニズムは大きく2つです。

第一に、NUMA balancingティアリングモード(NUMAB-2)。 アクセス確認用のページフォールト(prot_none)で熱いページを見つけ、プロセス自身のコンテキストで昇格を実行します。つまり昇格作業がアプリケーションの実際の処理と同じスレッドで起きます。降格はreclaimベースで、kswapdまたはdirect reclaimが処理します。

第二に、DAMONとその上のDAMOS。 DAMONはカーネルスレッドを立ち上げてメモリアクセスを5msごとにサンプリングし、結果を100msごとにユーザースペースへ渡します。一般的なシステムでのオーバーヘッドは0.1%未満だと、DAMONの創始者SeongJae ParkがLSFMM+BPF 2026で発表しています。5.15で初めてマージされました。DAMOSはその観測結果に動作を紐づける層であり、ティアリングに使われる動作がmigrate_hot(昇格)とmigrate_cold(降格)です。核心的な違いは、DAMOSが非同期のワーカースレッドで動くという点です。

この違いが、後で数字となって返ってきます。

2026年7月時点でmainlineに実際に入っているもの

発表資料やニュースではなく、カーネルソースを直接確認しました。以下は各機能が最初に現れるタグをinclude/linux/damon.hとドキュメントで確認した結果です。

6.11    DAMOS_MIGRATE_HOT / DAMOS_MIGRATE_COLD
        (v6.10には無い -> v6.11で登場。SK hynix: Hyeongtak Ji, Honggyu Kim, 2024-06-14)
        HMSDKのCXL容量拡張用。閾値は人が手で入れる静的な値。

6.16    node_mem_used_bp / node_mem_free_bp クォータ目標
        (自己チューニングティアリング、通称TPP-DAMON。SeongJae Park)

6.17    damos->migrate_dests — 複数の宛先ノード + 重み
        (Micron: Bijan Tabatabai。仮想アドレス空間専用)

6.19    node_memcg_used_bp / node_memcg_free_bp
        (cgroup単位のティアリング。Metaとの協業)

7.2-rc1 node_eligible_mem_bp
        (Micron: Ravi Jonnalagadda。まだ正式リリースされたカーネルには入っていない)

ここで2点を指摘しておく必要があります。

第一に、「入れれば動く」ティアリングカーネルモジュールは存在しません。 v7.2-rc3のmm/damon/Kconfigで「tier」という文字列は0回しか出てきません。ビルドされるDAMONモジュールはDAMON_RECLAIMDAMON_LRU_SORTDAMON_STATの3つだけで、mm/damon/配下にtiering.cはありません。つまりmainlineが与えるのは部品(クォータ目標のmetric、マイグレーション動作、宛先の重み)であり、それを組み立てて方針にする作業はユーザースペースの仕事です。

これは事故ではなく計画どおりです。自己チューニングティアリングのRFCカバーレターで、著者自身がクォータ目標metricの部分を先に出し、ティアリングモジュールの部分は「後で」出すと書いています。理由は、モジュール側が2階層しか想定しておらず、ノードのアドレス範囲をユーザーが直接入力しなければならない、完成形とは程遠い状態だからというものでした。その「後で」は2026年7月現在まだ来ていません。

そのため今日これを回すには、発表スライドにあるようにdamoコマンドを自分で書く必要があります。

damo start \
  --numa_node 0 --monitoring_intervals_goal 4% 3 5ms 10s \
      --damos_action migrate_cold 1 --damos_access_rate 0% 0% \
      --damos_apply_interval 1s \
      --damos_quota_interval 1s --damos_quota_space 200MB \
      --damos_quota_goal node_mem_free_bp 0.5% 0 \
      --damos_filter reject young \
  --numa_node 1 --monitoring_intervals_goal 4% 3 5ms 10s \
      --damos_action migrate_hot 0 --damos_access_rate 5% max \
      --damos_apply_interval 1s \
      --damos_quota_interval 1s --damos_quota_space 200MB \
      --damos_quota_goal node_mem_used_bp 99.7% 0 \
      --damos_filter allow young \
      --damos_nr_quota_goals 1 1 --damos_nr_filters 1 1 \
  --nr_targets 1 1 --nr_schemes 1 1 --nr_ctxs 1 1

ノード0(DRAM)では冷めたページを降格しつつ空き容量0.5%を目標に、ノード1(CXL)では熱いページを昇格しつつDRAM使用率99.7%を目標に回す構成です。0.5%と99.7%をわずかに重なるように設定し、昇格と降格が互いを止めてしまわないようにするのが設計意図で、カバーレターはこの2つの値をデフォルトの推奨値として提案しています。悪くないインターフェースですが、これを「入れれば動く」と呼ぶのは難しいでしょう。

第二に、CONFIG_DAMONはデフォルトではありません。 2025年5月、SeongJae Parkは主要ディストリビューションがすでにDAMONをビルド有効化しており、カーネルパッケージサイズが約0.1%しか増えないという根拠でデフォルト有効化パッチを提出し、6.16-rc1のマージウィンドウに入りました。そして2025年6月10日、Linus Torvaldsがそれを差し戻しました。コミットaef17cb3d3c4の本文は一行です — "No, we don't make random features default to being on."

v7.2-rc3のmm/damon/Kconfigを確認すると、config DAMONには今もdefault yがありません。差し戻しはそのまま維持されています。

4.43%という数字 — そしてそれが測っていないもの

自己チューニングティアリング(6.16)に付随する数字が4.42%です。元のRFCカバーレター(SeongJae Park、2025-03-19)を読むと、条件が全部書かれています。

測定環境。 DRAM階層250 GiB、CXL階層50 GiBをそれぞれNUMAノード0と1として公開したマシン。カーネルはv6.13に2025-03-15時点のmmツリーのDAMONパッチ一式と当該シリーズを載せたもので、アプリケーションの従来のNUMA最適化が干渉しないようmempolicy()システムコールを無視するよう改変しています。ワークロードはDCPerfのTaobenchの変種で、メモリサイズ340 GiB、ウォームアップ2,500秒、測定1,440秒、RSSはウォームアップ中に270 GiBまで成長します。各構成につき5回反復。

結果表(カバーレター原文)。

Config         Score   Stdev   (%)     Normalized
Baseline       1.6165  0.0319  1.9764  1.0000
Numab_tiering  1.4976  0.0452  3.0209  0.9264
DAMON_tiering  1.6881  0.0249  1.4767  1.0443

自分で計算してみると、1.6881を1.6165で割ると1.0443なのでDAMONティアリングは4.43%改善、1.4976を1.6165で割ると0.9264なのでNUMAB-2は7.36%低下です。(カバーレターの要約部分は4.42%と7.34%と記していますが、表そのものから出てくる値は4.43%と7.36%です。1年後のLSFMMスライドにまで「~4.42%」がそのまま引き継がれています。些細なことですが、引用される数字が元の表を再計算した人の手を経ていないことも意味します。)

ここまでは良い知らせのように聞こえます。次に、同じカバーレターが自ら書き留めた留保点を見てみましょう。

ワークロードはもともと何の差も生みませんでした。 著者自身の記述をそのまま移すと、Taobenchはアクセスパターンが非常に静的で、RSSの約13%だけが最初から最後まで頻繁にアクセスされており、その結果、設計や実装が何であれ昇格は意味のある性能差を生みませんでした。そこで著者はカーネルを改変して、1分に1回、熱いページを最大10 GiB降格し冷めたページを最大10 GiB昇格させる撹乱を注入しました。アクセスパターンが周期的に変わる状況をシミュレートするためで、ワークロード名に「modified」が付いているのはこのためです。

つまり4.43%は、ティアリングに有利になるよう人為的に揺さぶられたワークロードから出た値です。揺さぶらなかった元のワークロードでは、どのティアリング実装も差を出せませんでした。

降格はまったく発生していません。 カバーレター自身が明かすとおり、シミュレーション用の撹乱がワークロード開始時から動いていたため、DRAM階層の使用量が常にウォーターマーク以下にとどまり、すべてのテスト実行で実際の降格は発生しませんでした。この表はLRUベースの降格とDAMONベースの降格を比較していません。含まれているのはNUMAB-2の昇格とDAMONの昇格の差だけです。

著者自身による限界の記述。 カバーレターには「Evaluation Limitations」という節が別途あり、見方によってはこの改変版Taobenchが図を歪めすぎているように見えかねず、より現実的なワークロードやより公正なマイクロベンチマークで評価するほうがよいと書かれています。著者が自分の数字についてこれ以上正直になるのは難しいでしょう。

そして標準偏差。 スコアに対する標準偏差は1.48%から3.02%です。4.43%はその上にありますが、圧倒的に上というわけではありません。

本当に興味深いのは別の行です。 同じテストで、NUMAB-2 — つまりカーネルにすでに入っている既存のティアリング機能 — はむしろ性能を7.36%下げました。 著者は、NUMAB-2の同期的な昇格がTaobenchの実際の処理進行を妨げたためだろうと推測しています。先に触れた「プロセスのコンテキストでの昇格」が、ここで代償を払ったわけです。

この表を一行でまとめるとこうです — ティアリングを入れる理由を無理やり作ったワークロードで、新方式は4.43%稼ぎ、既存方式は7.36%失いました。

25%という数字 — そしてそれが実はティアリングではないということ

6.17の複数宛先マイグレーションには25%が付随します。元のカバーレター(Bijan Tabatabai、Micron、2025-07-02)を見ると、これも条件が全部書かれており、先の話とは性格がまったく異なります。

測定環境。 128コア256スレッドのAMD CPU、ローカルDDR帯域幅72 GB/s、CXL帯域幅26 GB/s。ワークロードは帯域幅集約的なembedding reductionアプリケーションで、反復ごとに同じ割り当てを再利用し、反復あたりの所要時間を報告します。

手順。 最初はシステムの帯域幅使用率が低いので、インターリーブの重みを1対0に設定し、すべてローカルメモリに割り当てます。ワークロードが始まるとローカル帯域幅が飽和し、このタイミングで重みを3対1に変更してDAMONにデータを動かさせます。反復時間は7,600ms台から5,630ms台へ下がり、カバーレターはこれを約25%のspeedupと記しています。

ここで重要な転換。 これは「熱いものは速い階層、冷めたものは遅い階層」ではありません。むしろ逆で、熱いデータをわざと遅いCXLに載せて両階層の帯域幅を合算しているのです。容量ティアリングではなく帯域幅インターリービングです。

数字が辻褄が合うか自分で確認してみました。72足す26は98、98を72で割ると1.361なので、帯域幅がボトルネックなら時間は0.735倍になるはずです。7,620msに0.735を掛けると約5,600msで、実測は約5,634msです。誤差1%以内に収まります。重み3対1も、帯域幅の比72対26(約2.8対1)に沿っています。つまりこの25%は帯域幅の合算で説明がつき、それ以上でもそれ以下でもありません。純粋に帯域幅に律速されたワークロードでなければ、この利得は出ません。

そして最も正直であるべき部分。 重みを1対0から3対1に変えたのは人間です。 ちょうど帯域幅が飽和したその瞬間に。カバーレターはこの点を隠していません — このパッチセットは、データをどうインターリーブするかを変更するメカニズムを追加するだけであり、重みがいくつであるべきかという方針はユーザースペースに残すと明記しています。そして、システムの帯域幅使用率やアクセスレイテンシを監視して重みを調整するユーザースペースプログラムを作っているが、まだ公開の準備ができていないと記しています。

そのループを閉じる部品が、先のタイムラインにあったnode_eligible_mem_bpです。スキームのアクセスパターンに一致するメモリのうち特定ノードにある割合をbasis pointで測るmetricで、これを目標に掲げると「熱いデータの60%はDRAMに、40%はCXLに」といった分布をクォータのオートチューナーが自動的に維持します。コミット9138e27a3bc3(Ravi Jonnalagadda、Micron)がその実装です。

注目すべき点が3つ。第一に、このコミットは著者日付が2026-04-28、コミット日付が2026-05-29です。7.1-rc1は2026-04-26に出たので、これは7.1に間に合わず、実際DAMOS_QUOTA_NODE_ELIGIBLE_MEM_BPはv7.0にもv7.1にも無く、v7.2-rc1に初めて現れます。 v7.2はまだ正式リリースではないため(現時点の最新タグはv7.2-rc3です)、今日時点でこの機能が入った正式カーネルはまだ存在しません。 (LWNの記事はこの機能が7.1-rc1にマージされたと書いていますが、発表者本人のスライドは「7.1-rc1以降にmm-newへマージ」と書いており、ソースはスライド側の言い分を支持します。7.1-rc1に入ったのはクォータ目標のチューナーアルゴリズムのほうです。)

第二に、このコミットには性能の数字が一つもありません。 「Testing Results」節はあるものの、内容は2ノードの異種メモリシステムで機能検証を行ったこと、TEMPORALチューナーは目標分布に速く収束しCONSISTチューナーはより遅く収束すること、目標到達までの時間はワークロードの強度によって変わることだけです。収束動作の報告であって、speedupの報告ではありません。

第三に、CONFIG_DAMON_PADDRが必要です。物理アドレス空間でのみ動作します。一方、6.17の重み付きインターリービングは仮想アドレス空間専用です — folioがVMA内でマッピングされたオフセットによって宛先ノードを決めるためで、物理アドレスのスキームでそれを割り出すには高コストなrmapの走査が必要になるからです。つまりメカニズムとその自動チューニングの目標は、互いに異なるアドレス空間に住んでいることになります。

まとめると、25%は本物ですが、人間が手でスイッチを入れて得た値であり、そのスイッチを自動で入れてくれるものは1年後にようやく-rcに到着し、まだ性能の数字は付いていません。

94%という数字 — 条件のない数字

LSFMM+BPF 2026で最大の数字は94%でした。TPP-DAMONがシングルスレッドでは遅すぎたためマルチスレッドモデルに移行し、llama.cppベンチマークで94%の改善を出すという内容です。SK hynixの作業です。

発表者本人が公開したスライド原本を取得して確認すると、該当スライドはこうなっています — タイトル「Multi-thread Tiering (SK hynix)」、箇条書き3つ: サブリージョンごとのDAMONワーカースレッド、熱い/冷めたページ発見の高速化、マイグレーションの高速化。そして最後の箇条書き「Achieves ~94% llama.cpp speedup」。

それだけです。どんなハードウェアか、どんなモデルか、何との比較か、何回動かしたのか、何も書かれていません。この数字の条件を記した公開カバーレターを私は見つけられませんでした。DAMONプロジェクト自身のニュース一覧にもこの項目はありません。LWNの記事は同じ94%を伝えていますが、それは同じ発表を書き起こしただけなので独立した確認にはなりません。

これを「偽物」だと言っているのではありません。ただ、対比しておく価値はあります。4.43%にはハードウェア仕様、ワークロードのパラメータ、5回の反復、標準偏差の列、そして著者自身が書いた限界の節が付いています。94%には箇条書き一つが付いています。この分野では、数字の大きさと方法論の量はおおむね反比例します。 そしてスライドをさらに読み進めると、こう書かれています — TPP-DAMONは肯定的なテスト結果が「非公開で共有」され(privately shared)、これ以上の活発な開発計画はなく、サポートモードに入った、と。

つまりカーネルティアリングの看板であった自動チューニングモジュールは、公開された性能の裏付けなしに保守モードへ移行し、開発リソースはNUMA-TPP-DAMONという次のものへ移りました。それはスライドの表現で「ブレインストーミングレベルの初期構想」です。

本当の問題はアルゴリズムではなくパラメータだ

なぜこのコミュニティがここまで自動チューニングにこだわるのかは、ウィスコンシン大学の研究チームの論文がよく説明しています。From Good to Great: Improving Memory Tiering Performance Through Parameter Tuning(Kanellisら、arXiv:2504.18714、2025-04-25)のアブストラクトはこう述べています — 既存のティアリングソリューションはヒューリスティックとあらかじめ決めた閾値で配置・移行を決定するため、ワークロードやハードウェアに適応できず最適以下で動作する。

研究チームはベイズ最適化で既存のティアリングシステム(HeMemとSK hynixのHMSDK)のパラメータを探索し、値を正しく設定すれば同じシステムのデフォルト設定比で2倍、当時の最新ティアリングシステム比で1.56倍の性能が出ると報告しています。

この一文を先の4.43%の隣に置くと、図が鮮明になります。アルゴリズムを変えて得られるのは一桁パーセントですが、同じアルゴリズムのパラメータを正しく設定すれば2倍になります。ティアリングで値を決めているのはメカニズムではなくチューニングです。そしてデフォルト設定は半分を捨てているわけです。

同時に、これは悪い知らせでもあります。その2倍を得る方法がベイズ最適化、つまりワークロードごとに高コストな探索を回すことだからです。プロダクションでワークロードごとにパラメータスイープを回す余力のある組織は多くありません。カーネルがやろうとしている自己チューニングは、まさにこの探索をオンラインのフィードバックループで置き換えようとする試みであり、6.16の使用率・空き容量目標から7.2-rc1の分布目標までがその軌跡です。まだ到着していないだけです。

まだ解決していないこと

発表で出た未解決の課題が、この技術の今の成熟度を最も正確に語っています。

DAMONは誰がアクセスしたかを知りません。 自己チューニングティアリングのカバーレターが明示するとおり、この設計はCPU NUMAノードが1つの場合のみを想定しています。DAMONがアクセス情報の出所を知りえないため、CPU NUMAノードが複数あるシステムへの適用は複雑になると著者自身が書いています。2ソケットサーバーが珍しくないことを考えると、これは小さな注記ではありません。

DAMONとNUMA balancingは同じビットを取り合います。 両方ともpage-idleビットでアクセスを確認するため、互いが引き起こしたフォールトを相手が「測定」してしまいます。発表で出た候補案は、ビルド時排他(どちらか一方だけをカーネルに入れる)、実行時分離(一度に一方だけ有効化)、部分的な分離、そしてそのまま干渉させておく、でした。Parkの提案は、必要な整理作業が終わったら最初の実装はビルド時排他を使うか、いっそ問題を無視しようというものでした。排他に進めば、ディストリビューションはどちらかを選ばなければならない苦しい立場に置かれます。セッションでDavidlohr Buesoが、複数の層がメモリ配置の判断を巡って互いに争う問題を懸念したのも同じ文脈です。

次世代はまだアイデア段階です。 NUMA-TPP-DAMON — ティアリングをNUMA配置の特殊ケースとして一般化し、CPU・GPUなど複数のアクセサ(accessor)ごとに昇格経路を別々に回そうという構想は、ブレインストーミング段階であり、アクセサごとのモニタリングという難題がその前に立ちはだかっています。

そしてドキュメント。 node_eligible_mem_bpはv7.2-rc3のinclude/linux/damon.hにはありますが、DAMON設計文書のクォータ目標metric一覧にはまだありません。ドキュメントが遅れるのはよくあることですが、この機能がどれほど出来立てかを示す印ではあります。

で、あなたは今これを入れるべきか

入れる価値がある場合

  • サーバーがコアではなくメモリ容量に律速されており、ワークロードのメモリのかなりの部分が実際に冷めている。(MetaがVistaraの論文で報告したfleetの43.7%がこの状態でした。)
  • ワークロードが帯域幅に律速されており、CXLの帯域幅を合算して得るものがある。この場合は容量ティアリングではなく重み付きインターリービングを見るべきで、上の25%の事例の計算をあなたのハードウェアの数字でやり直せば上限がすぐ出ます。
  • パラメータを実際のワークロードでチューニングする余力がある。上の論文どおりなら、ここに2倍が眠っています。
  • CPU NUMAノードが1つである。

まだ早い場合

  • アクセスパターンが静的である。4.43%の実験の元のTaobenchがそうで、結果はどの実装でも意味のある差がありませんでした。ティアリングは熱さと冷たさが時間とともに変わるときに値を発揮します。変わらないなら動かす理由がありません。
  • 「入れれば勝手に動く」ことを期待している。mainlineにティアリングモジュールは無く、damoのコマンドラインといくつかの手で選んだ定数があなたのものです。
  • 2ソケット以上である。設計はまだその場合を想定していません。
  • レイテンシに敏感なサービスで余裕が乏しい。降格を誤れば、そのページの次のアクセスはCXLのレイテンシをそのまま被ります。
  • NUMAB-2を入れれば済むと思っている。上の表ではそれは7.36%の損でした。少なくともそのワークロードでは。

何をするにせよ、手順は一つです — あなたのワークロードのアクセスパターンをまず測ってください。 幸い、それは今や簡単です。DAMON_STATが6.17に入り、Debianのカーネルでビルド有効化されています。ページの何パーセントが何時間読まれていないかを知らないままティアリングを入れるのは、上の実験がまさに示すとおり、何でもないことにマイグレーションのオーバーヘッドを払うことです。

おわりに

まとめるとこうです。Linux mainlineは2024年の6.11から2026年の7.2-rc1まで、CXLティアリングの部品を着実に受け取ってきており、その部品の大半はメモリを売る会社(SK hynix、Micron)とメモリに資金が縛られている会社(Meta)自身が書いたコードです。部品そのものはよく設計されています。

ただ正直に言えば、今日のmainlineには入れれば動くティアリングモジュールは無く、CONFIG_DAMONはデフォルトでオフのままであり、自動チューニングの最後の部品はまだ正式リリースに入っておらず、看板モジュールは公開された性能の裏付けなしにサポートモードへ移行しました。引用される数字のうち最もよく文書化されているのは4.43%であり、それもワークロードを人為的に揺さぶって初めて出た値で、最大の数字である94%には条件が付いていません。

CXLが誇大宣伝されてきたという言葉はよく聞きます。カーネル側から見た図は少し違います — ここでの進捗は遅いが実在し、何より作業している人たち自身が自分の数字について極めて正直です。 カバーレターに「このワークロードは図を歪めすぎているように見えかねない」と書き、スライドに「結果は非公開で共有された」と書く人たちです。誇張はたいてい、このコードを書いている人たちではなく、それを要約して運ぶ層のほうで付け加えられます。

ですから、CXLティアリングを検討するなら、ベンダー資料の代わりにカバーレターを読んでください。そこには数字とともに、その数字が測っていないものの一覧がすでに書かれています。

参考資料