Salamander76 schrieb:
Ich möchte realisieren, dass die Rechenlast einer in JAVA entwickelten Anwendung
1. auf mehrere Cores eines Rechners oder
2. auf mehrere Prozessoren mehrerer Rechner
verteilt wird, um die Laufzeit zu optimieren.
Das ist aber schon eine recht komplexe Sache - insbesondere, da die Verteilung auf mehrere Rechner Netzwerkkommunikation beinhaltet, die für sich allein schon recht trickreich ist, wenn man es schnell und verlässlich haben möchte. Da sollten die Arbeitspakete nicht zu klein sein, weil sich sonst der Overhead für die Kommunikation nicht lohnt.
So wie ich das gelesen habe geht es nur, wenn man die einzelnen Teile der Anwendung als Thread programmiert.
Das kann man so allgemein nicht sagen. Es hängt davon ab, welches Framework Du verwendest. Wenn Du nur die Java-Standardbibliothek nimmst, dann hast Du allein schon mehrere Möglichkeiten - angefangen von Threads bis zum ExecutorService und implementierende Klassen.
Generell würde ich aber erst mal schauen, welche Frameworks es dafür bereits in Java gibt. Vielleicht wäre auch eher Erlang etwas für Deine Problemstellung, weil das genau auf die parallele Ausführung ausgelegt ist und Verteilung im Netz mitbringt.
Um den ersten Punkt zu realisieren, habe ich folgenden JAVA-Code programmiert.
Für Zeitmessungen nimmt man am besten System.nanoTime(), weil das genauer auflöst als System.currentTimeMillis(), das bei new Date()
verwendet wird.
Außerdem solltest Du Ausgaben von Threads vermeiden, da IO auf Stdout synchronisiert wird und generell erhebliche teurer ist als Berechnungen wie Deine.
Nun hätte ich erwartet, dass wenn man routine() in der main 2x hintereinander aufrufen würde, dies die doppelte Ausführungszeit beansprucht, wie wenn man diese über 2 Threads aufruft. Die Ausführungszeit ist jedoch ein beiden Fällen praktisch identisch.
Du führst routine()
gar nicht in den Threads aus, weil Du run()
überhaupt nicht überlädst. Dein Code macht folgendes:
zwei ThreadTest-Instanzen werden erzeugt (Achtung: es sind keine Thread-Instanzen und erzeugen != starten).
anstatt sie zu starten, rufst Du zwei mal hintereinander Deine Version von start()
im Main-Thread auf, von wo aus dann routine()
synchron aufgerufen wird. (Um die Threads parallel zu starten, müsstest Du die Klassen von Thread erben lassen und die originale Version von start() aufrufen.)
Im Main-Thread wird routine()
auch noch einmal aufgerufen.
Mit anderen Worten: da passiert nichts parallel und es gibt keine Threads. Die Zeit, die Du in main()
misst, beinhaltet drei Ausführungen von routine()
. Kein Wunder, dass Du da keine Verbesserungen siehst.
Aber selbst, wenn Du es richtig machen würdest (also von Thread erben, start()
nicht überladen und routine()
aus run()
aufrufen), könntest Du mit den Ergebnissen nichts anfangen. Da Du alles nur ein Mal ausführst und z.B. keine Aufwärmphase vorsiehst, in der der JIT den Code übersetzen kann, sind die Ergebnisse weit davon entfernt, was Du in einer echten Anwendung erwarten kannst, in der die gleiche Arbeit öfters ausgeführt werden wird.
Der eigentliche Hintergrund der ganze Sache ist, dass ich plane ein kleines Cluster aus (zunächst) 4 Raspberry Pi zu konfigurieren, um Berechnungen über die Pis zu verteilen. Wenn das dann funktioniert könnte ich das Cluster variabel vergrößern.
Dabei stellt sich mir jedoch die Frage, ob das über diesen Weg auch funktioniert...
Ja, ist aber ein sehr großer Schuh - insbesondere, wenn Du auch noch dynamisch den Cluster vergrößern und verkleinern willst, und insbesondere auch, da Du wenig Erfahrung mit Multithreading in Java hast. Da würde ich eher nach existierender Software suchen. Ein JEE-Container wie JBoss bringt auch schon einiges mit, das man dafür benötigt, z.B. Cluster-Support, Message Queueing und, wenn ich das richtig erinnere, Lastverteilung. Damit könnte man das ggf. hinbekommen. Ich würde allerdings erst mal nach Systemen schauen, die auf so eine Verteilung von Aufgaben auf mehrere Kerne und Knoten im Netz ausgelegt sind.
Ciao
robert
Edit: ein paar inhaltliche Fehler korrigiert.