最終更新:2026-10-12
C++ False Sharing とキャッシュライン¶
最近あるコードを見かけました。手動でアラインメントを行っていたので、アラインメントしない場合にはどのような影響があるのか調べてみました。
template <typename T>
class AtomicWithPadding {
private:
static constexpr int kCacheLineSize = 64;
uint8_t padding_before[kCacheLineSize];
public:
std::atomic<T> value;
private:
uint8_t padding_after[kCacheLineSize];
};
ここで、皆さんが面接で必ず問われるポイントが出てきます:
- Cache line
そこで、以下のような面接問題がありますが、答えられるでしょうか?
- cache lineとは何か?
- MESIプロトコルとは何か?
- False sharingとは何か?
- C++ではどのようにFalse sharingを回避・防止するのか?
- False sharingを回避するとどのようなメリットがあるのか?
- C++17以降にこの問題を解決するために提供された2つの機能をご存知ですか?
そこで、パフォーマンステストを探してきました。おおよその実装は次のとおりです:
- a、b、c、dの4つの変数を定義し、複数スレッドで共有する
- もう1つは、この4つの変数をアラインメントし、n個のスレッドを起動してスケジューリングさせる
以下がbenchmarkの結果です:
------------------------------------------------------------------
Benchmark Time CPU Iterations
------------------------------------------------------------------
singleThread 4.05 ms 4.04 ms 133
directSharing/real_time 8.78 ms 0.069 ms 77
falseSharing/real_time 8.81 ms 0.083 ms 74
noSharing/real_time 1.16 ms 0.071 ms 578
noSharingが非常に良い結果を出していることがわかります!キャッシュヒット率が大幅に向上しています。もちろん、ここでperfを使って分析するとさらに良いでしょう。L1 cache missを見ることができます。
以上の解答は知識星球で更新済みです。ぜひ一緒に議論して、コメント欄で交流しましょう。よろしくお願いします〜
関連トピック¶
- C++ Concurrency in Action 読書ガイド | C++那些事
- C++ デッドロック調査 | C++那些事
- C++ SIMD ベクトル化 | C++那些事
- C++17 並列 STL | C++那些事
- GDB マルチスレッド All-Stop デバッグ | C++那些事
- Helgrind 並行エラー検出 | C++那些事
- libev イベントループの原理 | C++那些事
- C++ std::thread の内部実装 | C++那些事
- C++ std::thread と jthread | C++那些事
- C++ マルチスレッド入門 | C++那些事