0

いくつかのルックアップを実行し、parallel.for を使用して発生をカウントするコードがいくつかあります。

//...initialize _table with int values...
int elements=60;
int[] outerCounter=new int[elements];
Parallel.For(1, 2000, i0=>
{
  int[] counter=new int[elements];
  int nextPos0=_table[10+i0];
  for(i1=i0+1; i1<1990; i1++){ 
    //...here are also some additionale calculations done...  

    int nextPos1=_table[nextPos0+i1];
    counter[nextPos1]++;
  }
  //synchronize
  for(int i=0; i<elements;i++){
    Interlocked.Add(ref outerCounter[i], counter[i]);
  }
}

このバージョンは、逐次計算よりもはるかに高速です。しかし、Interocked.Add がボトルネックであるため、発生をカウントする別の解決策を見つけたいと思います。Plinq がオプションになるかどうかを調査していましたが、配列内の nextPos1 要素の出現をカウントする方法を見つけることができませんでした。

4

3 に答える 3

0

すべてのスレッドがoutcounterのすべての値に書き込むため、outcounter[i]をロックせずにこれを正しく行うことはできません。

于 2011-03-16T17:34:23.523 に答える
0

基本的に Hans と同じことを提案しますが、コードを提供すると役立つと思いました。私がおそらく問題に取り組む方法は次のとおりです。

//...initialize _table with int values...
int elements=60;
List<int[]> outerCounter=new List<int[]>();
Parallel.For(1, 2000, i0=>
{
  int[] counter;
  lock(outerCounter)
  {
    if (outerCounter.Count == 0)
      counter = new int[elements];
    else
    {
      counter = outerCounter[outerCounter.Count - 1];
      outerCounter.RemoveAt(outerCounter.Count - 1);
    }
  }
  int nextPos0=_table[10+i0];
  for(i1=i0+1; i1<1990; i1++){ 
    //...here are also some additionale calculations done...  

    int nextPos1=_table[nextPos0+i1];
    counter[nextPos1]++;
  }
  lock (outerCounter)
    outerCounter.Add(counter);
});

int totalCounter = new int[elements];
Parallel.For(0, elements - 1, i =>
{
  foreach (int[] counter in outerCounter)
    totalCounter[i] += counter[i];
});
于 2011-03-16T18:22:41.777 に答える
0

ここでパーティーに少し遅れましたが、counter[] と outerCounter[] の値をインクリメントするだけの場合は、オーバーロードされたバージョンの Parallel.For() を使用できます。
ループごとに要素のローカル配列を作成する代わりに、次のことができます。実行に対してローカルに 1 つ作成します (一度に 1 つのスレッドによってのみ操作されます)。次に例を示します。

int elements=60;
int[] outerCounter=new int[elements];

Parallel.For (1, 2000,
  () => new int[elements],                        // Initialize the local value.    
  (i0, state, counter) =>
    {
        int nextPos0=_table[10+i0];
        for(i1=i0+1; i1<1990; i1++)
        { 
            //...here are also some additionale calculations done...  
            int nextPos1=_table[nextPos0+i1];
            counter[nextPos1]++;
        }
    }

  counter =>                                    // Add the local value
    { 
        for(int i=0; i<elements;i++)
        {
            Interlocked.Add(ref outerCounter[i], counter[i]);
        }
    }
);

上記のコードをテストしていませんが、それが要点です。Interlocked.Add() を呼び出す回数が大幅に削減されます

詳細については、このサイトが非常に優れています: http://www.albahari.com/threading/part5.aspx

于 2011-03-23T06:28:33.740 に答える