Mit Parallel Linq Extensions zur Vereinigung von zwei Sequenzen, wie kann man zuerst die schnellsten Ergebnisse erzielen?

9

Nehmen wir an, ich habe zwei Sequenzen, die die Ganzzahlen 1 bis 5 zurückgeben.

Der erste gibt 1, 2 und 3 sehr schnell zurück, aber 4 und 5 benötigen jeweils 200 ms.

%Vor%

Die Sekunde gibt 1, 2 und 3 mit einer Verzögerung von 200ms zurück, aber 4 und 5 werden schnell zurückgegeben.

%Vor%

Vereinigen beide diese Sequenzen geben mir nur die Nummern 1 bis 5.

%Vor%

Ich kann nicht garantieren, welche der beiden Methoden zu welchem ​​Zeitpunkt verzögert wird, daher kann die Reihenfolge der Ausführung keine Lösung für mich garantieren. Daher möchte ich die Union parallelisieren, um die (künstliche) Verzögerung in meinem Beispiel zu minimieren.

Ein realistisches Szenario: Ich habe einen Cache, der einige Entitäten zurückgibt, und eine Datenquelle, die alle Entitäten zurückgibt. Ich möchte in der Lage sein, einen Iterator von einer Methode zurückzugeben, die die Anforderung sowohl an den Cache als auch an die Datenquelle intern parallelisiert, so dass die zwischengespeicherten Ergebnisse so schnell wie möglich ausgegeben werden.

Hinweis 1: Ich merke, dass es immer noch CPU-Zyklen verschwendet; Ich frage nicht, wie ich verhindern kann, dass die Sequenzen über ihre langsamen Elemente iterieren, wie ich sie so schnell wie möglich verbinden kann.

Update 1: Ich habe achitaka-sans Antwort darauf angepasst, mehrere Produzenten zu akzeptieren und ContinueWhenAll zu verwenden, um die CompleteAdding-Funktion von BlockingCollection nur einmal zu setzen. Ich habe es einfach hier hingelegt, da es durch die fehlende Formatierung der Kommentare verloren gehen würde. Jede weitere Rückmeldung wäre großartig!

%Vor%     
Alex Norcliffe 09.11.2011, 13:25
quelle

2 Antworten

3

Sehen Sie sich das an. Die erste Methode gibt einfach alles zurück, um die Ergebnisse zu erhalten. Die zweite prüft die Eindeutigkeit. Wenn Sie sie verketten, erhalten Sie das gewünschte Ergebnis, denke ich.

%Vor%     
achitaka-san 09.11.2011, 14:04
quelle
0

Der Cache wäre fast augenblicklich im Vergleich zum Abrufen von der Datenbank, also könnten Sie zuerst aus dem Cache lesen und diese Elemente zurückgeben, dann aus der Datenbank lesen und die Elemente mit Ausnahme derjenigen zurückgeben, die im Cache gefunden wurden.

>

Wenn Sie versuchen, dies zu parallelisieren, werden Sie eine Menge Komplexität hinzufügen, aber einen ziemlich kleinen Gewinn erzielen.

Bearbeiten:

Wenn es keinen vorhersehbaren Unterschied in der Geschwindigkeit der Quellen gibt, könnten Sie sie in Threads ausführen und einen synchronisierten Hash-Satz verwenden, um zu verfolgen, welche Elemente Sie bereits erhalten haben, die neuen Elemente in eine Warteschlange zu legen und die Haupt-Thread aus der Warteschlange gelesen:

%Vor%

Teststream:

%Vor%

Test:

%Vor%     
Guffa 09.11.2011 13:41
quelle