Parallele For-Schleife in C# mit der freigegebenen variable
Ich versuche, parallele Verarbeitung zu beschleunigen, ein paar von verschachtelten Schleifen, aber ich habe Probleme dabei, die syntax Recht. Ich bin versuchen, um eine zu zählen, wie viele Pixel in einer bitmap sind entweder rot, weiß oder schwarz, die Werte, für die habe ich in einem enum anderswo.
In der seriellen Verarbeitung habe ich folgenden code, der gut funktioniert:
Bitmap image = new Bitmap(@"Input.png");
var colourCount = new int[3];
for (var x = 0; x < image.Width; x++)
{
for (var y = 0; y < image.Height; y++)
{
switch (image.GetPixel(x, y).ToArgb())
{
case (int)colours.red: colourCount[0]++; break;
case (int)colours.white: colourCount[1]++; break;
case (int)colours.black: colourCount[2]++; break;
default: throw new ArgumentOutOfRangeException(string.Format("Unexpected colour found: '{0}'", image.GetPixel(x, y).ToArgb()));
}
}
}
Habe ich gesehen-code für die parallele for-Schleifen, die von Microsoft und von Stackoverflow, das aktualisieren einer gemeinsamen Variablen wie unten:
Parallel.For<int>(0, result.Count, () => 0, (i, loop, subtotal) =>
{
subtotal += result[i];
return subtotal;
},
(x) => Interlocked.Add(ref sum, x)
);
Aber alle Beispiele verwenden eine einfache Art, wie ein int als die shared-variable und ich kann einfach nicht herausfinden, die syntax zu schreiben, um meine Größe von drei Arrays. Bin ich der Annäherung an diese alle falsch?
Übrigens, ich weiß in Bezug auf performance, GetPixel ist sehr langsam im Vergleich zu so etwas wie Bitmap.LockBits, ich versuche nur, um das Prinzip der parallelen Schleifen Recht.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Können Sie eine überlastung der
Parallel.Für
und ermöglicht es Ihnen, zu halten thread-lokale Zustand. In diesem Fall erstellen wir einint[3]
array für jeden thread, der erzeugt wird. Innerhalb jeder iteration der parallelen Schleife, die wir nur zu aktualisieren, die lokalen arraylocalColourCount
. Schließlich, wenn der thread zurückgezogen werden, aggregieren wir die Ergebnisse der einzelnen lokale array in das Globale,colourCount
; da dies jedoch ist eine gemeinsame Datenstruktur, setzen wir den gegenseitigen Ausschluss beim Zugriff auf es.Diesem code wird davon ausgegangen, dass
Bitmap.GetPixel
thread-sicher ist, die möglicherweise oder möglicherweise nicht der Fall sein.Andere Sache, die Sie brauchen zu beachten ist, dass jede
ArgumentOutOfRangeException
Instanzen kombiniert in einemAggregateException
, so müssen Sie einstellen das error-handling-code.lock
in IhremlocalFinally
. Sie könnte stattdessen verwendenInterlocked.Add()
in der Schleife. Obwohllock
macht es offensichtlich richtig.Interlocked.Add
weniger effizient als ein einzelnerlock
. (Auf jeden Fall wäre der Fall, wenn diecolourCount
Bestand aus zehn Elementen; sicher nicht für 3.) Pro Albahari: "AlleInterlocked
's Methoden generieren einen vollständigen Zaun." Die wiederholte cache-Invalidierung Aufwand könnte mehr als die Kosten für die einzelne Sperre.