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[i],您将无法正确执行此操作,因为所有线程都将写入 outcounter 中的所有值。

于 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() 的重载版本,
而不是在每个循环中创建一个本地元素数组,你可以创建一个本地执行(并且一次只能由一个线程操作)例如:

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 回答