Frage

Ich habe einen Code, um einige Lookups durchzuführen und das Ereignis mit Parallel zu zählen.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]);
  }
}

Diese Version ist viel schneller als eine sequentielle Berechnung. Aber ich möchte eine andere Lösung finden, um das Ereignis als interocked.add zu zählen. Ich habe untersucht, ob Plinq eine Option wäre, aber nicht in der Lage war, einen Weg zu finden, um das Vorkommen der NextPOS1 -Elemente in einem Array zu zählen.

War es hilfreich?

Lösung

Ich würde im Grunde dasselbe wie Hans vorschlagen, aber ich dachte, es wäre nützlich, Code bereitzustellen. So würde ich wahrscheinlich das Problem angehen:

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

Andere Tipps

Nach dem, was ich aus dem Code bekomme, können Sie dies nicht korrekt tun, ohne die Outcounter zu sperren [i], da alle Threads in alle Werte in Outcounter schreiben.

Hier zu spät zu der Party hier, aber wenn Sie nur die Werte in Zähler [] und äußere [] inkrementieren, können Sie eine überlastete Version von parallel verwenden.FOR ()
Anstatt jeweils eine lokale Reihe von Elementen in jeder Schleife zu erstellen, können Sie beispielsweise einen lokalen zur Ausführung erstellen (und werden nur jeweils um einen Thread betrieben):

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

Ich habe den obigen Code nicht getestet, aber das ist der Jist davon. Es reduziert drastisch die Menge, mit der Sie Interlocked.Add () anrufen, drastisch.

Für weitere Informationen ist diese Website sehr gut:http://www.albahari.com/threading/part55.aspx

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top