Вопрос

У меня есть код, чтобы сделать некоторые поиски и подсчитать происшествие, используя параллель.

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

Эта версия намного быстрее, чем последовательный расчет. Но я хотел бы найти другое решение, чтобы подсчитать происшествие как соединение. Адд - узкое место. Я исследовал, будет ли Plinq вариантом, но не смог найти способ подсчитать происхождение элементов NextPos1 в массиве.

Это было полезно?

Решение

Я бы в основном предложил бы то же самое, что и Ганс, но я подумал, что было бы полезно предоставить какой -то код. Вот как я бы, наверное, решил проблему:

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

Другие советы

Из того, что я получаю от кода, вы не сможете сделать это правильно, не блокируя Outcounter [i], поскольку все потоки будут писать все значения в Outcounter.

Немного опаздывает в сторону здесь, но если вы только увеличиваете значения на счетчика [] и 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]);
        }
    }
);

Я не проверил приведенный выше код, но это этот жист. Это значительно уменьшит количество раз, когда вы называете взаимосвязанным. ADD ()

Для получения дополнительной информации этот сайт очень хороший:http://www.albahari.com/threading/part5.aspx

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top