Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

False sharing of guarded member variables?

Tags:

Consider:

class Vector
{
  double x, y, z;
  // …
};

class Object
{
  Vector Vec1, Vec2;
  std::mutex Mtx1, Mtx2;

  void ModifyVec1() { std::lock_guard Lock(Mtx1); /* … */ }
  void ModifyVec2() { std::lock_guard Lock(Mtx2); /* … */ }
};

If either the mutexes or the guarded variables are stored contiguously and they share a cache line when cached, can this cause a sort of “cross-locking”?

If so, is it a good practice to declare the mutexes right after (or before) the variable they guard?

Aligning the class to std::hardware_destructive_interference_size (P0154) might avoid this effect. Are the potential benefits worth the overalignment of the object?

like image 965
metalfox Avatar asked Sep 16 '16 11:09

metalfox


People also ask

How would you fix the false sharing issue that can occur?

In general, false sharing can be reduced using the following techniques: Make use of private or threadprivate data as much as possible. Use the compiler's optimization features to eliminate memory loads and stores. Pad data structures so that each thread's data resides on a different cache line.

What is false sharing in a multiprocessor system and how does it affect performance?

False sharing occurs when threads on different processors modify variables that reside on the same cache line. This invalidates the cache line and forces an update, which hurts performance. False sharing is a well-know performance issue on SMP systems, where each processor has a local cache.

How do I stop false sharing on OpenMP?

In OpenMP programs False sharing arises when several threads maintain their respective partial result in a vector indexed by the thread rank. Replacing this with thread local variables often helps. Avoid writing to global data that is accessed from multiple threads. Align shared global data to cache line boundaries.

What is false sharing in the context of multithreading?

"false sharing" is something that happens in (some) cache systems when two threads (or rather two cores) writes to two different variables that belongs to the same cache line.


1 Answers

Your variables seem unrelated in your question, so rather than hardware_destructive_interference_size you probably want hardware_constructive_interference_size:

struct keep_together {
    std::mutex m;
    Vector v;
};

alignas(std::hardware_constructive_interference_size) keep_together k1;
alignas(std::hardware_constructive_interference_size) keep_together k2;

destructive you want to use for cases like lock-free queues, were threads are reading two different atomics and you want to make sure they both actually get loaded. If that's an issue here, you'll need to explain why false sharing is what you're avoiding.

Is it a good practice to declare the mutex right after (or before) the variable it guards to increase the chance they are on the same cache line?

That's constructive interference.

like image 80
Barry Avatar answered Sep 24 '22 16:09

Barry