Wie werden asynchrone Vorgänge in einem TPL Dataflow für die beste Leistung ausgeführt?

8

Ich habe die folgende Methode geschrieben, um eine riesige CSV-Datei stapelweise zu verarbeiten. Die Idee besteht darin, einen Teil der Zeilen aus der Datei in den Speicher einzulesen und diese Zeilen dann in Stapel fester Größe aufzuteilen. Sobald wir die Partitionen erhalten haben, senden Sie diese Partitionen an einen Server (sync oder async), was eine Weile dauern kann.

%Vor%

Dieser Codeabschnitt scheint aus zwei Gründen nicht sehr effizient zu sein.

  1. Der Haupt-Thread, der aus der CSV-Datei liest, wird blockiert, bis alle Partitionen verarbeitet sind.

  2. Die AsParallel-Blöcke, bis alle Aufgaben abgeschlossen sind. Wenn also im Thread-Pool mehr Threads für die Arbeit verfügbar sind, verwende ich sie nicht, da die Anzahl der Tasks durch keine der Partitionen gebunden ist.

Die Batchgröße ist fest, kann also nicht geändert werden, aber chunkSize ist für die Leistung einstellbar. Ich kann eine ausreichend große ChunkSize wählen, so dass keine der erstellten Chargen & gt; & gt; keine der im System verfügbaren Threads, aber es bedeutet immer noch, dass die Parallel.ForEach-Methode blockiert, bis alle Aufgaben abgeschlossen sind.

Wie kann ich den Code so ändern, dass alle verfügbaren Threads im System genutzt werden, um die Arbeit ohne Leerlauf zu erledigen? Ich denke, ich könnte eine BlockingCollection verwenden, um die Chargen zu speichern, aber nicht sicher, welche Kapazitätsgröße es geben soll, da keine Charge in jedem Chunk dynamisch ist.

Irgendwelche Ideen, wie man TPL benutzt, um die Thread-Auslastung zu maximieren, so dass die meisten verfügbaren Threads auf dem System immer Sachen machen?

UPDATE: Das habe ich bisher mit TPL-Datenfluss gemacht. Ist das korrekt?

%Vor%     
user330612 16.08.2015, 04:19
quelle

1 Antwort

1

Sie waren in der Nähe, in TPL Daten fließt von einem Block zum anderen, und Sie sollten versuchen, dieses Paradigma zu halten. So sollte zum Beispiel action1 ein TransformManyBlock sein, weil ein ActionnBlock ein ITargetBlock ist (d. H. Ein Terminierungsblock).

Wenn Sie für einen Link die Propagierungsvervollständigung angeben, wird das vollständige Ereignis automatisch durch den Block geleitet, sodass Sie nur eine Wartezeit () für den letzten Block ausführen müssen.

Stellen Sie sich eine Dominos-Kette vor, die Sie im ersten Block als abgeschlossen bezeichnen und die sich durch die Kette bis zum letzten Block fortpflanzt.

Sie sollten auch überlegen, was und warum Sie Multithreading sind; Ihr Beispiel ist stark I / O-gebunden, und ich glaube nicht, dass das Binden eines Threads, der auf die I / O-Vervollständigung warten soll, die richtige Lösung ist.

Bedenken Sie, was blockiert wird oder nicht. In Ihrem Beispiel ist buffer1.Post (...) nicht ein blockierender Aufruf, Sie haben keinen Grund, das in einer Aufgabe zu haben.

Ich habe den folgenden Beispielcode geschrieben, der TPL DataFlow verwendet:

%Vor%     
Julien Lebot 23.08.2015, 13:35
quelle