SeniorPerformanceOccasionalNot answered yet
What is false sharing, and how do you eliminate it?
False sharing is when two threads write distinct variables that share one cache line — each write invalidates the other core's copy, causing line ping-pong. Fix it by aligning hot data to std::hardware_destructive_interference_size.
- ✗Confusing false sharing with a real data race — it is a correctness-neutral performance bug, not a logic error
- ✗Packing per-thread counters into a tight array or struct, so adjacent elements share a cache line
- ✗Hardcoding 64 as the line size instead of
hardware_destructive_interference_size
- →How would you detect false sharing with
perfor VTune? - →What is true sharing, and why can padding not fix it?
Contents
What happens
Cache coherence works at the granularity of a cache line (typically 64 bytes), not individual bytes. If two variables sit on the same line, a write to either marks the whole line dirty and invalidates other cores' copies — even if the threads are logically independent.
struct Counters {
std::atomic<long> a; // both fields
std::atomic<long> b; // on one cache line
};
Counters c;
// Thread 1: loop c.a.fetch_add(1)
// Thread 2: loop c.b.fetch_add(1)
// Logically independent, yet the line ping-pongs between cores.
How to fix it
Push the hot fields onto separate lines via alignment:
struct Counters {
alignas(std::hardware_destructive_interference_size)
std::atomic<long> a;
alignas(std::hardware_destructive_interference_size)
std::atomic<long> b;
};
Or manual padding if the constant is unavailable:
struct alignas(64) PaddedCounter {
std::atomic<long> value;
char pad[64 - sizeof(std::atomic<long>)];
};
Notes
- This is not a correctness problem: the unpadded program computes the right answer, just slowly. That makes false sharing hard to spot without a profiler.
- The cost is memory: each padding wastes up to a line per object, so only align data that is genuinely hot and concurrently written.
hardware_destructive_interference_sizeis the minimum offset guaranteed to avoid false sharing;hardware_constructive_interference_sizeis the opposite — the max size for placing data together.
Contents