Art des Lastenausgleichs-Thread-Pools in Java

8

Ich bin auf der Suche nach einem Load-Balanced-Thread-Pool, der bisher keinen Erfolg hat. (Nicht sicher, ob Lastverteilung die richtige Formulierung ist). Lassen Sie mich erklären, was ich erreichen möchte.

Teil 1: Ich habe Jobs mit 8 bis 10 Einzelaufgaben. Auf einer 6-Kern-CPU lasse ich 8 Threads parallel an diesen Aufgaben arbeiten, was die beste Leistung zu liefern scheint. Wenn eine Aufgabe bereit ist, kann eine andere beginnen. Sind alle zehn Aufgaben erledigt, ist der komplette Job erledigt. Normalerweise ist ein Job in 30 bis 60 Sekunden erledigt.

Teil zwei: Manchmal dauert der Job mehr als zwei Stunden. Dies ist aufgrund der Menge an Daten, die berechnet werden müssen, korrekt. Das Schlimme daran ist, dass während der Ausführung von job1 kein anderer Job gestartet werden kann (vorausgesetzt, dass alle Threads die gleiche Dauer haben), da alle Threads verwendet werden.

Meine erste Idee: 12 Threads haben, erlauben bis zu drei Jobs parallel. ABER: das bedeutet, dass der cou nicht vollständig ist, wenn es nur einen Job gibt.

Ich suche nach einer Lösung, um die volle CPU-Leistung für den ersten Job zu haben, wenn es keinen anderen Job gibt. Aber wenn ein anderer Job gestartet werden muss, während ein anderer läuft, möchte ich, dass die CPU-Leistung beiden Jobs zugewiesen wird. Und wenn ein dritter oder vierter Job auftaucht, möchte ich, dass die CPU-Leistung allen vier Jobs zugewiesen wird.

Ich schätze Ihre Antworten ...

Danke im Voraus

    
Christian Rockrohr 19.01.2013, 14:26
quelle

3 Antworten

6

Eine Möglichkeit könnte darin bestehen, ein Standard- ThreadPoolExecutor mit einer anderen Art von Aufgabenwarteschlange zu verwenden

%Vor%

Die Idee hier ist, dass Sie, wenn Sie einen neuen Job haben,

anrufen %Vor%

und die Aufgaben so aufreihen, dass sie sich gut mit eventuell vorhandenen Aufgaben in der Warteschlange verschachteln (falls vorhanden). Angenommen, Sie haben einen Job in der Warteschlange, dessen Aufgaben die Prioritätszahlen j 1 t 1 <3>, j 1 2 haben > = 103 und j 1 t 3 3 = 203. In Ermangelung anderer Jobs werden diese Aufgaben so schnell wie möglich nacheinander ausgeführt. Wenn Sie jedoch einen anderen Job mit drei eigenen Tasks übergeben, erhalten diese Prioritätsnummern j 2 <1> <4> 2 = 104 und j 2> t 3 = 204, was bedeutet, dass die Warteschlange nun aussieht wie

j 1 t 1, j 2 t 1, j 1 t 2, j 2 t 2, usw.

Dies ist jedoch nicht perfekt, da, wenn alle Threads gerade funktionieren (auf Tasks von Job 1), die erste Task von Job 2 erst dann gestartet werden kann, wenn eine der Aufgaben von Job 1 abgeschlossen ist (es sei denn, es gibt einen externen Weg) Sie dies zu erkennen und einige Aufgaben von Job 1 zu unterbrechen und erneut in die Warteschlange stellen. Der einfachste Weg, um die Dinge fairer zu machen, wäre, die länger laufenden Aufgaben in kleinere Segmente aufzuteilen und diese als separate Aufgaben in die Warteschlange zu stellen. Sie müssen an einen Punkt kommen, an dem jeder einzelne Job mehr Aufgaben als Threads im Pool umfasst. so dass einige der Aufgaben immer in der Warteschlange beginnen und nicht direkt Threads zugewiesen werden (wenn es inaktive Threads gibt, übergibt exec.execute() die Aufgabe direkt an einen Thread, ohne die Warteschlange zu durchlaufen).

    
Ian Roberts 19.01.2013, 15:06
quelle
1

Am einfachsten ist es, Ihre CPU zu überzeichnen, wie Kanaga es vorschlägt, aber starten Sie jeweils 8 Threads. Es kann einige Overhead von der Konkurrenz geben, aber wenn Sie zu einer einzelnen Arbeitssituation kommen, wird es die CPU voll ausnutzen. Das Betriebssystem behandelt die Zeit für jeden Thread.

Ihre "erste Idee" würde auch funktionieren. Die inaktiven Threads würden keine Ressourcen aus 8 aktiven Threads beanspruchen, wenn sie tatsächlich keine Task ausführen. Dies würde die CPU-Ressourcen jedoch nicht gleichmäßig verteilen, wenn mehrere Jobs ausgeführt werden.

Haben Sie ein Setup, bei dem Sie diese verschiedenen Pipelines testen können, um zu sehen, wie sie für Sie funktionieren?

    
Joshua Martell 19.01.2013 15:20
quelle
1

Ich denke, da Ihre Maschine 6-Kern-CPU ist. Besser 6 Worker-Threads für jeden Job-Thread. Wenn also ein Thread einen neuen Job erhält, werden bis zu sechs parallele Mitarbeiter an dem einzelnen Job arbeiten. Dadurch wird sichergestellt, dass die volle CPU-Leistung verbraucht wird, wenn immer nur ein Job zur Verfügung steht.

Sehen Sie sich auch das Konzept von Fork and Join in Java 7 an.
References_1
References_2
Referenzen_3
Referenzen_4

Informieren Sie sich auch über newcachedthreadpool ()

Java newCachedThreadPool () und newFixedThreadPool

    
Kanagavelu Sugumar 19.01.2013 14:43
quelle