Frage

Gibt es eine integrierte Unterstützung in der TPL (Aufgabe-Parallel-Library) zum Dosieren von Operationen?

Ich war vor kurzem mit einer Routine spiele auf einem Zeichenarray auszuführen Zeichenersetzung eine Lookup-Tabelle mit d Umschrift:

for (int i = 0; i < chars.Length; i++)
{
    char replaceChar;

    if (lookup.TryGetValue(chars[i], out replaceChar))
    {
        chars[i] = replaceChar;
    }
}

Ich konnte sehen, dass dieser triviale parallelisiert werden konnte, so sprang mit einem ersten Stich, die ich wusste, dass schlechter abschneiden als die Aufgaben waren zu feinkörnig:

Parallel.For(0, chars.Length, i =>
{
    char replaceChar;

    if (lookup.TryGetValue(chars[i], out replaceChar))
    {
        chars[i] = replaceChar;
    }
});

ich überarbeitete dann den Algorithmus zu verwenden Dosierung, so dass die Arbeit auf verschiedene Threads in weniger feinkörnig Chargen gestückelt werden. Dies machte den Einsatz von Threads wie erwartet, und ich habe einige in der Nähe von linearer Geschwindigkeit auf.

Ich bin sicher, dass es muss eingebaut werden Unterstützung in der TPL Dosieren. Was ist die Syntax, und wie kann ich es verwenden?

const int CharBatch = 100;
int charLen = chars.Length;

Parallel.For(0, ((charLen / CharBatch) + 1), i =>
{
    int batchUpper = ((i + 1) * CharBatch);

    for (int j = i * CharBatch; j < batchUpper && j < charLen; j++)
    {
        char replaceChar;

        if (lookup.TryGetValue(chars[j], out replaceChar))
        {
            chars[j] = replaceChar;
        }
    }
});

Aktualisieren

Nach der Verwendung von @ Oliver Antwort und ersetzt Parallel.For mit einem Parallel.ForEach und Partitioner der Code lautet wie folgt:

const int CharBatch = 100;

Parallel.ForEach(Partitioner.Create(0, chars.Length, CharBatch), range =>
{
    for (int i = range.Item1; i < range.Item2; i++)
    {
        char replaceChar;

        if (lookup.TryGetValue(chars[i], out replaceChar))
        {
            chars[i] = replaceChar;
        }
    }
});
War es hilfreich?

Lösung

Für immer besser Ihren Kopf um Sie sollten die Muster für die parallele Programmierung: Verstehen und Parallel Patterns mit dem .NET Framework 4 Anwendung. Es ist eine große Quelle und erklärt die gemeinsame Möglichkeiten auf, wie die TPL verwenden.

Schauen Sie sich auf Seite 26 (sehr kleinen Schleifenkörper). Dort werden Sie dieses Beispiel finden:

Parallel.ForEach(Partitioner.Create(from, to), range =>
{
    for (int i = range.Item1; i < range.Item2; i++)
    {
        // ... process i
    }
});

So das fehlende Stück Sie suchen ist die System.Concurrent.Collections.Partitioner .

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