user2425056
user2425056

Reputation: 327

How to lock array for aggregation in Parallel.For

I am trying to iterate through a 2D array and then add to parts of another 2D array in a Parallel.For loop. I have found examples where an accumulation is being done inside the loop on a single variable but am not sure what to do here. GridB is doing accumulation so surely it needs to be locked as items in it could be added to from different threads If it needs to be locked how do you go about locking an entire array like this?

int[,] GridA = new int[D + 2, D + 2];
int[,] GridB = new int[D + 2, D + 2];

Parallel.For(1, D+1 , r =>
{
for (int c = 1; c <= D ; c++)
    if (GridA[r, c] != 0)
    {
        int v = GridA[r, c];

        GridB[r - 1, c - 1] += v;
        GridB[r - 1, c] += v;
        GridB[r - 1, c + 1] += v;

        GridB[r, c - 1] += v;
        GridB[r, c + 1] += v;

        GridB[r + 1, c - 1] += v;
        GridB[r + 1, c] += v;
        GridB[r + 1, c + 1] += v;
    }
});

Upvotes: 3

Views: 490

Answers (1)

Mike Zboray
Mike Zboray

Reputation: 40838

You could just lock GridB like so:

Parallel.For(1, D+1 , r =>
{
  for (int c = 1; c <= D ; c++)
  {
    if (GridA[r, c] != 0)
    {
      int v = GridA[r, c];
      lock(GridB) 
      { 
        GridB[r - 1, c - 1] += v;
        // etc.
      }
    }
  }
});

However, you are serializing all access to GridB which sort of defeats the purpose of using multiple threads.

If all you want to do is add a fixed value to each element, Interlocked.Add in the System.Threading namespace will do the add atomically, so you don't need to take out a lock on the whole array.

Here's a sample of the usage:

Parallel.For(1, D+1 , r =>
{
    for (int c = 1; c <= D ; c++)
      if (GridA[r, c] != 0)
      {
         int v = GridA[r, c];

          Interlocked.Add(ref GridB[r - 1, c - 1], v);
          // rinse, repeat
      }
}

Upvotes: 1

Related Questions