Restartable Sequences の理解: Mutex と Atomics に代わる高性能な選択肢

極限のパフォーマンスを追求する際、開発者は同期処理において壁に突き当たることがよくあります。Mutex や atomic 操作のような従来のツールは、複数のスレッド間でデータの整合性を確保するための標準的な手法ですが、オーバーヘッドという代償を伴います。コア数が増加するにつれ、これらのロックに対する競合は重大なボトルネックとなり、CPU サイクルの浪費やレイテンシの増加を招く可能性があります。

Restartable sequences (rseq) は、Linux カーネルがクリティカルセクションを処理する方法におけるパラダイムシフトを表しています。重厚なロック機構に頼るのではなく、rseq は、プリエンプション(中断)が発生した場合にカーネルによって安全に中断・再開できる短い命令シーケンスの実行をプログラムに許可します。これにより、ユーザースペースのメモリ更新に対して実質的に「トランザクション的」なアプローチを提供します。

Restartable Sequences の仕組み

rseq の核心は、クリティカルセクション中のプリエンプションの問題に対処するように設計されていることです。典型的なシナリオでは、スレッドがロックを保持したままプリエンプションされると、他のスレッドがスピンしたりブロックしたりして、リソースを浪費します。Restartable sequences を使用すると、カーネルはスレッドが進入するクリティカルセクションを認識できるようになります。

コミュニティの議論で指摘されているように、このメカニズムは次のように機能します。

"It works is you advise the kernel whenever your program enters a critical section of code that you don't want interrupted... The first assembly opcode should be a move instruction that sets the rseq_cs field. The last instruction needs to be the thing that makes the modification to your global data structure."

このプロセスは、小さなユーザースペースのトランザクションを作成します。ユーザースペースのアプリケーションとカーネルの間の通信は双方向であり、共有メモリを介して行われるため、クリティカルセクション中の高価なシステムコールを排除できます。カーネルがスレッドをプリエンプトするか、あるいはスレッドが別の CPU にマイグレーション(移動)された場合、カーネルは rseq_cs フィールドが設定されていることを検出し、自動的に命令ポインタをシーケンスの開始点にリセットします。これにより、操作が再開され、スレッドの実行に対してアトミックに完了することが保証されます。

パフォーマンスの利点: Atomics を超えて

rseq に関する最も刺激的な主張の一つは、、CPU の内部的な atomic 操作さえも上回るパフォーマンスを発揮できる可能性があるということです。Atomics は Mutex よりも高速ですが、コア間でのキャッシュラインの同期が必要であり、これは高コンカレンシー(高並列性)環境において高価になる可能性があります。

rseq を使用することで、開発者は特定のホットパスから Mutex と Atomics の両方を排除できる可能性があります。カーネルが再開ロジックを管理するため、アプリケーションは単純な load と store を実行できます。プリエンプションが発生しなければ、コードは生のメモリアクセスの速度で動作します。プリエンプションが発生した場合、コストは非常に短い命令シーケンス(通常は 10 命令以下)の再開となります。これは、競合するロックのオーバーヘッドよりもはるかに効率的です。

実装とツール

基礎となるメカニズムにはアセンブリと共有メモリ構造が含まれますが、多くの開発者にとって、rseq をゼロから実装する必要はありません。エコシステムは、より高レベルな抽象化を提供するために進化してきました。

これをプロジェクトに統合したいと考えている方には、librseq ライブラリ(rseq 実装者によって維持されています)が、カウンタや連結リストなどの一般的なユースケースに不可欠なヘルパーを提供しています。これにより、開発者は、すべてのクリティカルセクションに対してカスタムのアセンブリを記述することなく、Restartable sequences のパフォーマンスの利点を得ることができます。

検討事項とトレードオフ

パフォーマンスの向上にもかかわらず、rseq は万能薬ではありません。これは、非常に短いクリティカルセクションに特化して最適化されています。シーケンスが長すぎると、プリエンプションの確率が高まり、頻繁な再開が発生し、パフォーマンスが低下する可能性があります。

さらに、一部の開発者は、rseq の利点点は、膨大なコア数を持つ環境で最も顕著になると主張しています。アプリケーション開発者が少数のスレッドを完全に制御できるシナリオでは、rseq と従来の thread-local storage や最適化された atomics の差はより狭くなる可能性があります。しかし、ハードウェアが数百コアに向けてスケールアップし続ける中で、CPU コア数に合わせてスケールする能力は、決定的な利点となります。

結論

Restartable sequences は、「アトミック性」の責任を「ハードウェア (atomics)」または「OS スケジューラ (mutexes)」から、両者の協力関係へとシフトさせることで、同期オーバーヘッドを削減する洗練された方法を提供します。共有メモリを介してクリティカルセクションをクリティカルセクションを再起動可能なトランザクションとして扱うことで、Linux は、ハイパフォーマンス・コンピューティングにおける真の線形スケーリングへの道を提供します。

Sources