False sharing between threads is when 2 or more threads use the same cache line.
E.g. :
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 threads in the first block do suffer from false sharing. The threads in the second block do not (thanks to CACHELINE_SIZE
).
Data on the stack is always 'far' away from other threads. (E.g. under windows, at least a couple of pages).
With your definition of a function object, false sharing can appear, because the instances of Work
get created on the heap and this heap space is used inside the thread.
This may lead to several Work
instances to be adjacent and so may incur sharing of cache lines.
But ... your sample does not make sense, because data is never touched outside and so false sharing is induced needlessly.
The easiest way, to prevent problems like this, is to copy your 'shared' data locally on tho the stack, and then work on the stack copy. When your work is finished copy it back to the output var.
E.g:
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 problems with sharing.
static
data, then all the threads will share that data. – Exhortative