Verschachtelte Java 8 parallele forEach-Schleife durchführen Armen. Ist dieses Verhalten zu erwarten?

Hinweis: ich habe bereits angesprochen, dieses problem in einem anderen, SO post - Die Verwendung einer semaphore innerhalb einer geschachtelten Java 8 parallel-stream handeln, kann der DEADLOCK. Ist das ein bug? -, aber der Titel von diesem post vorgeschlagen, dass das problem bezieht sich auf die Verwendung eines semaphor - die etwas abgelenkt der Diskussion. Ich bin zu erstellen, diese zu betonen, dass die nested loops-vielleicht ein performance-Problem, - obwohl beide Probleme haben wahrscheinlich eine gemeinsame Ursache (und vielleicht, weil es hat mich eine Menge Zeit, um herauszufinden, dieses problem). (Ich sehe es nicht als eine doppelte, denn Sie betonen ein weiteres symptom - aber wenn Sie das tun, löschen Sie ihn einfach).

Problem: Wenn Sie nest zwei Java 8 stream.parallel().forEach-Schleifen und alle Aufgaben sind unabhängig, staatenlos, etc. - außer für die übergabe an die gemeinsame FJ pool -, dann nisten parallele Schleife innerhalb eines parallelen Schleife führt, die viel ärmer als das verschachteln einer sequentiellen Schleife in eine parallele Schleife. Noch schlimmer: Wenn der Vorgang mit der inneren Schleife synchronisiert wird, erhalten Sie eine SACKGASSE.

Demonstration des performance-Problems

Ohne die "synchronisiert" Sie können immer noch beobachten, wie ein performance-problem. Finden Sie einen demo-code für diese an: http://svn.finmath.net/finmath%20experiments/trunk/src/net/finmath/experiments/concurrency/NestedParallelForEachTest.java
(siehe die JavaDoc gibt es eine ausführliche Beschreibung).

Unserem setup ist wie folgt: Wir haben eine geschachtelte stream.parallel().forEach().

  • Die innere Schleife ist unabhängig (staatenlos, keine Störungen, etc. - außer der Verwendung einer gemeinsamen pool) und verbraucht 1 Sekunde in der Summe im schlimmsten Fall, nämlich dann, wenn sequentiell verarbeitet.
  • Die Hälfte der Aufgaben der äußeren Schleife verbrauchen 10 Sekunden vor dieser Schleife.
  • Hälfte verbrauchen 10 Sekunden nach dieser Schleife.
  • Damit jeder thread verbraucht 11 Sekunden (worst case) insgesamt.
     * Wir haben ein boolean, welcher erlaubt das Umschalten der inneren Schleife von der parallelen (), um sequentiell().

Nun: Vorlage 24 äußere-Schleife-Aufgaben zu einem pool mit Parallelität 8 wir würden erwarten, dass 24/8 * 11 = 33 Sekunden im besten Fall (auf einem 8-core oder besser Maschine).

Ist das Ergebnis:

  • Mit inneren sequentiellen Schleife: 33 Sekunden.
  • Mit innere parallele Schleife: >80 Sekunden (ich hatte 92 Sekunden).

Frage: Können Sie bestätigen, dass dieses Verhalten? Ist das etwas, was man erwarten würde, die aus dem Rahmen? (Ich bin ein bisschen vorsichtiger jetzt mit einer Forderung, dass das ein bug ist, aber ich persönlich glaube, dass es aufgrund von einen bug in der Implementierung von ForkJoinTask. Bemerkung: ich habe diese Gleichzeitigkeit-Interesse (siehe http://cs.oswego.edu/pipermail/concurrency-interest/2014-May/012652.html ), aber bisher habe ich keine Bestätigung bekommen von dort).

Demonstration der deadlock -

Dem folgenden code wird die DEADLOCK -

    //Outer loop
    IntStream.range(0,numberOfTasksInOuterLoop).parallel().forEach(i -> {
        doWork();
        synchronized(this) {
            //Inner loop
            IntStream.range(0,numberOfTasksInInnerLoop).parallel().forEach(j -> {
                doWork();
            });
        }
    });

wo numberOfTasksInOuterLoop = 24, numberOfTasksInInnerLoop = 240, outerLoopOverheadFactor = 10000 und doWork einige Staatenlose CPU-burner.

Finden Sie eine komplette demo-code bei http://svn.finmath.net/finmath%20experiments/trunk/src/net/finmath/experiments/concurrency/NestedParallelForEachAndSynchronization.java
(siehe die JavaDoc gibt es eine ausführliche Beschreibung).

Ist dieses Verhalten zu erwarten? Beachten Sie, dass die Dokumentation der Java-parallel streams erwähnt keinerlei Problem mit der Verschachtelung oder Synchronisation. Auch die Tatsache, daß beide eine gemeinsame fork-join-pool ist nicht erwähnt.

Update

Weiteren test auf dem performance-Problem kann gefunden werden, an http://svn.finmath.net/finmath%20experiments/trunk/src/net/finmath/experiments/concurrency/NestedParallelForEachBenchmark.java
- dieser test kommen, ohne Blockierung der Bedienung (kein Gewinde.schlafen und nicht synchronisiert). Ich erstellte einige weitere Anmerkungen hier: http://christian-fries.de/blog/files/2014-nested-java-8-parallel-foreach.html

Update 2

Scheint es, als ob dieses problem und desto schwerer DEADLOCK mit Semaphoren wurde behoben in Java8 u40.

  • Vielleicht lohnt sich verknüpfen die Gleichzeitigkeit Interesse Diskussion: cs.oswego.edu/pipermail/concurrency-interest/2014-May/...
  • Dass die Parallelität Interesse die Diskussion ist sehr merkwürdig. Was mir auffällt ist, wie viel alle Mitglieder der Gruppe bestehen auf Dinge wie "der Programmierer sollte wissen, dass F/J ist xyz" oder "der Programmierer verwenden sollten <xyz von F/J framework>" für "diese" aber durch die Suche des gesamte Dokumentation java.util.stream fand ich keine Erwähnung der F/J framework überhaupt. Ich erinnere mich an die Erwähnung von F/J als detail irgendwo, aber das ist ein völlig anderes Bild.
  • Fries keine news auf, dass die Frage noch nicht?
Schreibe einen Kommentar