Java Multi-Threading Anfänger Fragen

8

Ich arbeite an einer wissenschaftlichen Anwendung, die leicht trennbare Teile aufweist, die parallel ablaufen können. Also habe ich diese Teile für jeden Lauf als unabhängige Threads geschrieben, aber nicht für das, was der Standardgrund für die Trennung von Dingen in Threads zu sein scheint (d. H. Nicht, einen Quit-Befehl oder ähnliches zu blockieren).

Ein paar Fragen:

Kauft mir das wirklich alles auf Standard-Mehrkern-Desktops - d. h. werden die Threads tatsächlich auf den separaten Kernen laufen, wenn ich eine aktuelle JVM habe, oder muss ich etwas anderes machen?

Ich habe wenige Objekte, die von allen Threads gelesen (aber nie geschrieben) werden. Mögliche Probleme damit? Lösungen für diese Probleme?

Können Sie für tatsächliche Cluster Frameworks empfehlen, um die Threads an die verschiedenen Knoten zu verteilen, so dass ich sie nicht selbst verwalten muss (nun, wenn solche existieren)? Erläuterung: Darunter verstehe ich entweder etwas, das automatisch Threads in Task für einzelne Knoten umwandelt oder den gesamten Cluster wie eine einzelne JVM aussehen lässt (d. H., Er könnte Threads an alle Prozessoren senden, auf die er zugreifen kann) oder was auch immer. Im Grunde genommen, implementieren Sie die Parallelisierung in einer nützlichen Weise auf einem Cluster, vorausgesetzt, dass ich es in den Algorithmus mit der minimalen Job-Haltung meinerseits eingebaut habe.

Bonus: Der Großteil der Auswertung besteht aus Mengenvergleichen (z. B. Vereinigung, Schnittpunkt, Enthält) mit einer Zuordnung von Schlüsseln, um die relevanten Mengen zu erhalten. Ich habe eine begrenzte Erfahrung mit FORTRAN, C und C ++ (Semester des wissenschaftlichen Rechnens für die ersten und HS AP-Klassen vor 10 Jahren für die anderen beiden) - welche Art von Geschwindigkeit / Leichtigkeit der Parallelisierung könnte ich finden, wenn ich meine gebunden Java-Front-End zu einem algorithmischen Back-End in einer dieser Sprachen, und welche Art von Kopfschmerzen könnte mein Erfahrungsstand finden, diese Operationen in diesen Sprachen zu implementieren?

    
Carl 07.10.2009, 16:48
quelle

3 Antworten

7
  • Ja, die Verwendung unabhängiger Threads verwendet mehrere Kerne in einer normalen JVM, ohne dass Sie irgendwelche Arbeiten ausführen müssen.

  • Wenn irgendetwas nur gelesen wird, sollte es in Ordnung sein, von mehreren Threads gelesen zu werden. Wenn Sie die fraglichen Objekte unveränderlich machen können (zu Garantie werden sie nie geändert), ist das sogar noch besser

  • Ich bin mir nicht sicher, welche Art von Clustering Sie in Betracht ziehen, aber Sie sollten sich vielleicht Hadoop ansehen. Beachten Sie, dass verteiltes Computing Tasks anstatt Threads verteilt (normalerweise sowieso).

Jon Skeet 07.10.2009, 17:05
quelle
5

Mehrkernnutzung

In Java-Laufzeiten werden Threads normalerweise so geplant, dass sie gleichzeitig auf allen verfügbaren Prozessoren und Kernen ausgeführt werden. Ich denke, es ist möglich, dies zu beschränken, aber es würde zusätzliche Arbeit erfordern; Standardmäßig gibt es keine Einschränkung.

Unveränderbare Objekte

Deklarieren Sie für schreibgeschützte Objekte ihre Mitgliedsfelder als final , wodurch sichergestellt wird, dass sie zugewiesen werden, wenn das Objekt erstellt und nie geändert wird. Wenn ein Feld nicht final ist, kann es auch in einem Multithread-Programm einige "Sichtbarkeitsprobleme" geben, selbst wenn es sich nach der Konstruktion nie geändert hat. Dies kann dazu führen, dass die Zuweisungen eines Threads für einen anderen nicht sichtbar werden.

Alle änderbaren Felder, auf die mehrere Threads zugreifen, sollten als volatile deklariert, durch Synchronisation geschützt werden oder einen anderen Mechanismus für den gemeinsamen Zugriff verwenden, um sicherzustellen, dass Änderungen konsistent und unter den Threads sichtbar sind.

Verteiltes Rechnen

Das am häufigsten verwendete Framework für verteilte Verarbeitung dieser Art in Java heißt Hadoop. Es verwendet ein Paradigma namens map-reduce.

Native Code Integration

Die Integration mit anderen Sprachen wird sich wahrscheinlich nicht lohnen. Aufgrund seines adaptiven Bytecode-zu-Native-Compilers ist Java bei einer Vielzahl von Rechenaufgaben bereits extrem schnell. Es wäre falsch anzunehmen, dass eine andere Sprache schneller ist, ohne tatsächlich getestet zu werden. Außerdem ist die Integration mit "nativem" Code unter Verwendung von JNI äußerst mühsam, fehleranfällig und kompliziert; Die Verwendung einfacherer Schnittstellen wie JNA ist sehr langsam und würde Leistungsverbesserungen schnell löschen.

    
erickson 07.10.2009 17:21
quelle
1

Wie einige Leute gesagt haben, sind die Antworten:

  1. Threads auf Kernen - Ja. Java hatte lange Zeit Unterstützung für native Threads. Die meisten Betriebssysteme haben Kernel-Threads bereitgestellt, die automatisch für alle CPUs eingeplant werden, die Sie haben (die Implementierungsleistung kann je nach Betriebssystem variieren).

  2. Die einfache Antwort ist, dass es im Allgemeinen sicher ist. Die komplexere Antwort ist, dass Sie sicherstellen müssen, dass Ihr Objekt tatsächlich erstellt wird & amp; initialisiert, bevor irgendwelche Threads darauf zugreifen können. Dies wird auf zwei Arten gelöst:

    • Lassen Sie den Klassenlader das Problem lösen, indem Sie ein Singleton (und das Laden von faulen Klassen) verwenden:

      %Vor%
    • Explizite Verwendung der Semantik zum Akquirieren / Freigeben, um ein konsistentes Speichermodell sicherzustellen:

      %Vor%

    Ich erinnere mich nicht von Anfang an, wie Sie das Speichermodell von Java für den letzteren Fall ausnutzen können. Ich glaube, wenn ich mich richtig erinnere, dass ein Schreiben in eine flüchtige Variable einer Freisetzungsbarriere gleichkommt, während ein Lesen von einer flüchtigen Variablen einer Erwerbbarriere entspricht. Der Grund dafür, dass der boolesche flüchtige Wert im Gegensatz zu dem Objekt gebildet wird, besteht darin, dass der Zugriff auf eine flüchtige Variable aufgrund der Speichermodellbeschränkungen teurer ist. Daher ermöglicht der boolesche Wert das Erzwingen des Speichermodells & amp; dann kann der Objektzugriff viel schneller innerhalb des Threads erfolgen.

  3. Wie bereits erwähnt, gibt es alle möglichen RPC-Mechanismen. Es gibt auch RMI, ein nativer Ansatz zum Ausführen von Code auf Remote-Zielen. Es gibt auch Frameworks wie Hadoop, die eine vollständigere Lösung bieten, die möglicherweise besser geeignet ist.

  4. Wenn man nativen Code aufruft, ist das ziemlich hässlich - Sun rät wirklich davon ab, JNI zu einem hässlichen komplizierten Chaos zu machen, aber es ist möglich. Ich weiß, dass es mindestens ein kommerzielles Java-Framework zum Laden & amp; native dynamische Bibliotheken ausführen, ohne sich um JNI kümmern zu müssen (nicht sicher, ob es freie oder OSS-Projekte gibt).

Viel Glück.

    
Vitali 07.10.2009 17:50
quelle