3

2D 配列を反復処理してから、Parallel.For ループで別の 2D 配列の一部に追加しようとしています。単一変数のループ内で累積が行われている例を見つけましたが、ここで何をすべきかわかりません。GridB は蓄積を行っているため、別のスレッドから追加できるアイテムとしてロックする必要があることは確かです ロックする必要がある場合、このように配列全体をどのようにロックしますか?

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;
    }
});
4

1 に答える 1

1

GridB次のようにロックできます。

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.
      }
    }
  }
});

GridBただし、複数のスレッドを使用する目的を無効にするすべてのアクセスをシリアル化しています。

各要素に固定値を追加するだけの場合Interlocked.AddSystem.Threading名前空間では追加がアトミックに行われるため、配列全体のロックを解除する必要はありません。

使用例は次のとおりです。

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
      }
}
于 2013-06-03T01:19:02.913 に答える