False separation between threads is that two or more threads use the same cache line.
eg.
struct Work { Work( int& d) : data( d ) {} void operator()() { ++data; } int& data; }; int main() { int false_sharing[10] = { 0 }; boost::thread_group threads; for (int i = 0; i < 10; ++i) threads.create_thread(Work(false_sharing[i])); threads.join_all(); int no_false_sharing[10 * CACHELINE_SIZE_INTS] = { 0 }; for (int i = 0; i < 10; ++i) threads.create_thread(Work(no_false_sharing[i * CACHELINE_SIZE_INTS])); threads.join_all(); }
The flows in the first block really suffer from a false exchange. Threads in the second block are not (thanks to CACHELINE_SIZE ).
Stack data is always "far" from other threads. (For example, under the windows, at least a couple of pages).
False sharing may appear with your definition of a function object, because Work instances are created on the heap, and this heap space is used inside the stream.
This can cause multiple Work instances to be contiguous and therefore can share cache lines.
But ... your sample does not make sense, because the data is never affected externally, and therefore false sharing is useless to induce.
The easiest way to prevent such problems is to copy your βsharedβ data locally onto the stack, and then work with a copy of the stack. When your work is finished, copy it back to the var output.
For example:
struct Work { Work( int& d) : data( d ) {} void operator()() { int tmp = data; for( int i = 0; i < lengthy_op; ++i ) ++tmp; data = tmp; } int& data; };
This prevents all sharing issues.
Christopher
source share