2012-11-24 15 views
7

Ich möchte die Task Parallel Library (TPL) in F # verwenden, um viele (> 1000) lange laufende Aufgaben auszuführen. Hier ist meine aktuellen Code:TPL Parallel.Für lange laufende Aufgaben

Parallel.For(1, numberOfSets, fun j -> 
    //Long running task here 
    ) 

Als ich dies beginnen, es scheint, dass .NET alle Aufgaben auf einmal und prallt zwischen ihnen löst sich ständig. Was wäre besser, wenn es bei einer Aufgabe bleibt, bis es fertig ist, bevor es zur nächsten geht. Dies würde die Kontextumschaltung minimieren.

Gibt es eine Möglichkeit, dem Scheduler einen Hinweis zu geben? Ich weiß, dass es möglich ist, Hinweise zu geben, aber ich kann keine klaren Beispiele finden, oder ist der Scheduler diesbezüglich schon schlau und es ist nur meine Wahrnehmung, dass es zu viele Kontextwechsel gibt. Danke für die Hilfe!

Antwort

8

Wir hatten ein ähnliches Problem - mit C# statt F #, aber die Bibliotheken sind die gleichen. Die Lösung war, den Grad der Parallelität zu begrenzen:

ParallelOptions parallelOptions = new ParallelOptions(); 
parallelOptions.MaxDegreeOfParallelism = 16; 
Parallel.For(0, n, parallelOptions, i => { 
    . . . 
}); 

16 gut für unsere Aufgaben gearbeitet - Sie sollten, welcher Wert zu sehen experimentieren ist besser in Ihrem Fall.

+0

+1, Sekunden schneller als ich :) –

+0

Sollte die MaxDegreeOfParallelism von der Anzahl der Kerne auf Ihrer Maschine abhängen? –

+0

@Wallhood: wahrscheinlich ja, wenn die Aufgabe CPU-gebunden ist, wenn die Aufgabe IO-gebunden ist (Dateiverarbeitung, Zugriff auf eine DB) wahrscheinlich nicht. In unserem Fall funktionierte dieser Wert auf 2/4 Kernen in normalen Situationen gut, es gab keinen wirklichen Grund, etwas anspruchsvolleres zu versuchen - es ist kein Programm, das zum Beispiel auf einer 16-Kern-Super-Maschine läuft. – MiMo

5

Aus meiner Erfahrung ist es für eine große Anzahl von Aufgaben besser, MaxDegreeOfParallelism linear an Environment.ProcessorCount zu binden.

ist hier ein ähnliches Codefragment zu @ one Mimo in F # Syntax:

let options = ParallelOptions() 
options.MaxDegreeOfParallelism <- Environment.ProcessorCount * 2 

Parallel.For(0, n, options, 
      (fun i -> (* Long running task here *))) |> ignore 

Da Sie mit der parallelen Programmierung in F # arbeiten, "Parallel Programming with Microsoft .NET", bitte einen Blick auf die ausgezeichneten Buch nehmen vor allem das Kapitel auf "Parallel Loops". @Tomas hat seine Samples in F # übersetzt und sie sind verfügbar here.

1

an der Referenzquelle sucht, scheint es das folgende Stück Code bestimmt die Anzahl der Arbeiter:

// initialize ranges with passed in loop arguments and expected number of workers 
int numExpectedWorkers = (parallelOptions.EffectiveMaxConcurrencyLevel == -1) ? 
    Environment.ProcessorCount : 
    parallelOptions.EffectiveMaxConcurrencyLevel; 

Soweit ich das beurteilen kann, mit den Standard-Task-Scheduler und Standard ParallelOptions dies Environment.ProcessorCount auswertet, Es ist also seltsam, dass Sie ein anderes Verhalten erhalten, wenn Sie MaxDegreeOfParallelism für die Prozessoranzahl angeben. Ich schlage vor, Sie debuggen, um sicherzustellen, dass es wirklich einen Unterschied gibt (Sie konnten die Thread.ManagedThreadId innerhalb der lang laufenden Aufgabe drucken).

+0

Es gab einen wesentlichen Unterschied. Wenn ich die Max Concurrency anwählte, würde es nur eine Aufgabe pro Kern gleichzeitig öffnen. Wenn ich es nicht spezifizierte, würde es alle Aufgaben auf einmal öffnen.Es hat vielleicht immer nur eins nach dem anderen funktioniert, aber es waren alle offen. Ich folge daraus, dass ich Timer für jede Aufgabe starte. Als ich die Parallelität spezifizierte, war die Zeit für jede Aufgabe die gleiche. Wenn ich es nicht getan habe, konnte die Ausführung der Aufgaben sehr lange dauern. Was darunter vorgeht, weiß ich nicht, aber das waren meine Beobachtungen. –

+0

Vielleicht sind die Anzahl der Arbeiter und 'MaxDegreeOfParallelism' zwei verschiedene Dinge? Ich bestätige, was @Wallhood sagt: ohne 'MaxDegreeOfParallelism' zu setzen, als wir 1000 Aufgaben hatten, die alle parallel gestartet wurden und sie die Maschine blockierten, wurde das Problem auf 16 gesetzt (unsere Aufgabe ist nicht CPU, sondern hauptsächlich Datenbank gebunden) – MiMo

Verwandte Themen