Can vector cause false sharing

can std::vector cause false sharing?

Containers aren't something that "cause" false sharing. It's writing to objects that may cause false sharing. Specifically, writing in one thread to an object that is in the same "cache line" as another object that is accessed in another thread causes false sharing.

Elements of an array are adjacent in memory and hence adjacent small elements of an array are very likely in the same cache line. Vector is an array based data structure. The pattern of accessing the elements of the vector in your example are a good example of false sharing.

is there any method to avoid false sharing while using std::vector to store the results of threads?

Don't write into adjacent small elements of an array (or a vector) from multiple threads. Ways to avoid it are:

  • Divide the array into contiguous segments and only access any individual segment from a separate thread. The size of the partition must be at least the size of the cache line on the target system.
  • Or, write into separate containers, and merge them after the threads have finished.

Yes, if you write to two adjacent int elements inside a std::vector, it is likely that they will both be on the same cache line, which will cause false sharing if this cache line is accessed simultaneously by two different threads.

C++17 introduced std::hardware_destructive_interference_size, which is a portable way to get a hint from the compiler on what the L1 cache line size is expected to be on the target platform.

Therefore, to prevent false sharing, you should ensure that the two int variables are at least std::hardware_destructive_interference_size bytes apart:

void func() {

    constexpr int min_offset = std::hardware_destructive_interference_size / sizeof(int);

    std::vector<int> res( min_offset + 1, 0 );
    std::thread t1( task1, &res[0] );
    std::thread t2( task2, &res[min_offset] );
    t1.join();
    t2.join();
    return res[0] + res[min_offset];
}

However, at the time of this writing, several compilers do not (yet) support std::hardware_destructive_interference_size. See this question for further information.

If you want to be reasonably certain that your code will not have false-sharing in the distant future, then you may want to assume that the cache size is double the size reported by std::hardware_destructive_interference_size.