スピンロックを最適化して5.7倍高速化、消費エネルギーも5.4分の1に

Optimizing a Spin-Lock

スピンロックを最適化して5.7倍高速化、消費エネルギーも5.4分の1に

スピンロックを段階的に改良し、最終的にナイーブ実装より5.7倍高速で消費エネルギーが5.4分の1になるまで最適化する過程を解説。メモリオーダリングの緩和、test-and-test-and-set、指数バックオフの導入により、4スレッド時のレイテンシは246nsから43.0nsへ、エネルギーは64.92Jから11.92Jへと大幅に削減される。ただし、通常はstd::mutexが適切なデフォルトであり、スピンロックはスレッドが専用コアに固定されている場合に測定してから検討すべきだと結論づけている。

スピンロックは決して眠らないロックだ。スケジューラに譲る代わりに、スレッドはCPU上に留まりスピンし続ける。システムコールもコンテキストスイッチもない。
  1. pizlonator

    マイクロベンチマークでロックのパフォーマンスを測るのは超危険。小さなベンチマークだと、CPUとメモリを非常に特殊で珍しい状態に置くことになる(ロック自体以外はすべて静か)。

    ロックの現実世界での話は通常、100%の時間で激しく競合しているわけではなく、ある程度の競合と、CPUが実際の仕事や実際のメモリアクセスを行っている状態が組み合わさっている。

    私が見つけたのは、そうしたより現実的なシナリオでは、マイクロベンチマークで最高のパフォーマンスを出すロックが、まったく異なる予想外のアルゴリズムと比べて崩壊してしまうということだ。

  2. vova_hn2

    素晴らしい関連記事、Travis Downs [1] による「A Concurrency Cost Hierarchy」[0] を共有したい。これはHNに何度も投稿されており [2]、最大の議論は26コメントある [3]。

    私自身のプログラミング経験は主にPythonなので、キャリアのほとんどを通じてロックは純粋な魔法として扱い、内部で何が起こっているかはあまり考えなかった。

    人生のある時点でRustと低レベルプログラミングに興味を持ち、特にこの記事がこのトピックについて頭を整理するのに本当に役立った。並行性プリミティブが実際にどのように機能するかを説明するだけでなく、なぜそう機能するのか、どのような選択とトレードオフが関与しているかも説明している。

    この記事はすべての例でC++を使用しているが、言語固有のものは本当に何もなく、すべての原則はRust、C、Zigなどでも機能する。

    [0] https://travisdowns.github.io/blog/2020/07/06/concurrency-co...

    [1] https://travisdowns.github.io/

    [2] https://hn.algolia.com/?q=https%3A%2F%2Ftravisdowns.github.i...

    [3] https://news.ycombinator.com/item?id=24489829

  3. tombert

    数年前にLMAX Disruptorを使い始めるまで、本番コードで実際にスピンロックを使っている人を聞いたことがなかった。

    常にアンチパターンだと言われてきたし、一般的にはかなり良い経験則だと思うが、CSのほとんどのことと同じで、「良い経験則」には常に例外があるのだろう。

    本番でスピンロックを明示的に書いたことはまだ実際にはないが、Disruptorはそれが適切なケースがあることを示してくれた。

  4. dalvrosa

    共有ありがとう!フィードバックをもらえると嬉しい :)

    ほとんどのケースではスピンロックを推奨しないことに注意。スレッドと物理CPUコアが1:1で対応している場合のみ、そして測定した後に限る。

  5. RossBencina

    TFAは電力使用量をドルコストの観点から言及しているが、熱の側面もある。ほとんど何もしていないときにサーマルスロットリングを引き起こしたり(あるいはブーストを失ったり)したくはない。

この日のほかの記事

2026-09-14