Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Memory barriers in Parallel.For

Microsoft's documention of Parallel.For contains the following method:

static void MultiplyMatricesParallel(double[,] matA, double[,] matB, double[,] result)
{
    int matACols = matA.GetLength(1);
    int matBCols = matB.GetLength(1);
    int matARows = matA.GetLength(0);

    // A basic matrix multiplication.
    // Parallelize the outer loop to partition the source array by rows.
    Parallel.For(0, matARows, i =>
    {
        for (int j = 0; j < matBCols; j++)
        {
            double temp = 0;
            for (int k = 0; k < matACols; k++)
            {
                temp += matA[i, k] * matB[k, j];
            }
            result[i, j] = temp;
        }
    }); // Parallel.For
}

In this method, potentially multiple threads read values from matA and matB, which were both created and initialized on the calling thread, and potentially multiple threads write values to result, which is later read by the calling thread. Within the lambda passed to Parallel.For, there is no explicit locking around the array reads and writes. Because this example comes from Microsoft, I assume it's thread-safe, but I'm trying to understand what's going on behind the scenes to make it thread-safe.

To the best of my understanding from what I've read and other questions I've asked on SO (for example this one), several memory barriers are needed to make this all work. Those are:

  1. a memory barrier on the calling thread after creating and intializing matA and matB,
  2. a memory barrier on each non-calling thread before reading values from matA and matB,
  3. a memory barrier on each non-calling thread after writing values to result, and
  4. a memory barrier on the calling thread before reading values from result.

Have I understood this correctly?

If so, does Parallel.For do all of that somehow? I went digging in the reference source but had trouble following the code. I didn't see any lock blocks or MemoryBarrier calls.

like image 693
adv12 Avatar asked Jan 14 '17 19:01

adv12


People also ask

What is the purpose of a memory barrier?

In computing, a memory barrier, also known as a membar, memory fence or fence instruction, is a type of barrier instruction that causes a central processing unit (CPU) or compiler to enforce an ordering constraint on memory operations issued before and after the barrier instruction.

Is volatile a memory barrier?

volatile in most programming languages does not imply a real CPU read memory barrier but an order to the compiler not to optimize the reads via caching in a register. This means that the reading process/thread will get the value "eventually".

What is memory barrier in Java?

Memory barriers, or fences, are a set of processor instructions used to apply ordering limitations on memory operations.

Is function call memory barrier?

The answer is: No. A function call is always a compiler barrier. But a function call is not guaranteed to be a memory barrier. It only is if the code in the called function contains a memory barrier.


1 Answers

Since the array is already created, writing or reading from it won't cause any resizes. Also, the code itself prevents reading/writing the same position in the array.

Bottom line is that the code always can calculate the position to read and write in the array and those calls never cross each other. Hence, it is thread-safe.

like image 147
Patrick Hofman Avatar answered Oct 21 '22 08:10

Patrick Hofman