False Sharing

Submit New Article

Last Modified On :   July 16, 2007 12:58 PM PDT
Rate
 



Challenge

Identify and eliminate false sharing in a threaded application. For example, two threads could use unique data elements on the same cache line for read and write. When one of the threads writes to this cache line, the same cache line referenced by the other thread is invalidated. Any new references to data in this cache line by the second thread results in a cache miss, and data will have to be loaded again from memory.

When thread functions are implemented as shown in the following code example, the global variable sumLocal causes false sharing, as both threads write to this array, and their distinct elements lie on the same cache line.

double sumLocal[N_THREADS];
. . . . .
. . . . .
void ThreadFunc(void *data)
{
   . . . . . . .
   int id = p->threadId;
   sumLocal[id] = 0.0;
   . . . . . .
   . . . . . .
   for (i=0; i<N; i++)
   sumLocal[id] += p[i];
   . . . . . .
}

 

Each time thread 1 writes to its element in the cache line, the cache copy of the same line for thread 2 is invalidated. Thread 2 now has to reload it into cache before it can write its element into the array. This in turn invalidates the copy owned by thread 1. If this type of activity were inadvertently introduced into an application, it could lead to severe degradation of performance.


Solution

Take either of the following two possible approaches:

  • Pad each thread's data element to ensure that elements owned by different threads all lie on separate cache lines.
     
  • Use a local copy from stack for all updates, and then perform a global update that reflects these updates to the global entity.
This problem usually manifests itself when applications use global state arrays to maintain information about each thread. This problem, if known, should be addressed (at least to some degree) at the design phase.

False sharing problems can also be identified during the tuning stage using the VTune™ Performance Analyzer, and the appropriate measures can be taken in that stage to address this problem. In all cases, developers should avoid false sharing by carefully dividing the work among the threads to cache line boundaries.
Source

Threading Methodology: Principles and Practices