2014-01-15 12 views
139

Mein Cluster: 1 Master, 11 Slaves, jeder Knoten hat 6 GB Speicher.Spark java.lang.OutOfMemoryError: Java-Heap-Speicher

Meine Einstellungen:

spark.executor.memory=4g, Dspark.akka.frameSize=512 

Hier ist das Problem:

Erste ich einige Daten lesen (2,19 GB) von HDFS RDD:

val imageBundleRDD = sc.newAPIHadoopFile(...) 

Zweite, tun Sie etwas auf dieser RDD:

val res = imageBundleRDD.map(data => { 
           val desPoints = threeDReconstruction(data._2, bg) 
           (data._1, desPoints) 
          }) 

Last, Ausgabe HDFS:

res.saveAsNewAPIHadoopFile(...) 

Wenn ich mein Programm ausführen es zeigt:

..... 
14/01/15 21:42:27 INFO cluster.ClusterTaskSetManager: Starting task 1.0:24 as TID 33 on executor 9: Salve7.Hadoop (NODE_LOCAL) 
14/01/15 21:42:27 INFO cluster.ClusterTaskSetManager: Serialized task 1.0:24 as 30618515 bytes in 210 ms 
14/01/15 21:42:27 INFO cluster.ClusterTaskSetManager: Starting task 1.0:36 as TID 34 on executor 2: Salve11.Hadoop (NODE_LOCAL) 
14/01/15 21:42:28 INFO cluster.ClusterTaskSetManager: Serialized task 1.0:36 as 30618515 bytes in 449 ms 
14/01/15 21:42:28 INFO cluster.ClusterTaskSetManager: Starting task 1.0:32 as TID 35 on executor 7: Salve4.Hadoop (NODE_LOCAL) 
Uncaught error from thread [spark-akka.actor.default-dispatcher-3] shutting down JVM since 'akka.jvm-exit-on-fatal-error' is enabled for ActorSystem[spark] 
java.lang.OutOfMemoryError: Java heap space 

Es gibt zu viele Aufgaben?

PS: Alles ist in Ordnung, wenn die Eingabedaten etwa 225 MB sind.

Wie kann ich dieses Problem lösen?

+0

wie Funken laufen kann? ist es von der Konsole? oder welche deploy-Skripte verwenden Sie? – Tombart

+0

Ich verwende sbt, um meine App zu kompilieren und auszuführen. sbt Paket dann sbt run. Ich habe das gleiche Programm vor einem Monat auf hadoop implementiert, und ich habe das gleiche Problem mit OutOfMemoryError, aber in hadoop kann es leicht gelöst werden, indem man den Wert von mapred.child.java.opts von Xmx200m auf Xmx400m erhöht. Hat Spark irgendeine jvm-Einstellung für seine Aufgaben? Ich frage mich, ob spark.executor.memory dieselbe Bedeutung hat wie mapred.child.java.opts in hadoop. In meinem Programm wurde spark.executor.memory bereits auf 4g viel größer als Xmx400m in hadoop eingestellt. Danke ~ – hequn8128

+0

Sind die drei Schritte, die Sie erwähnen, die einzigen, die Sie tun? Wie groß ist die Größe der von (data._1, desPoints) generierten Daten - dies sollte in den Speicher passen, insbesondere wenn diese Daten dann in eine andere Stufe verschoben werden. –

Antwort

13

Werfen Sie einen Blick auf the start up scripts eine Java-Heap-Größe wird dort festgelegt, es sieht so aus, als ob Sie dies vor dem Ausführen von Spark Worker nicht festlegen.

# Set SPARK_MEM if it isn't already set since we also use it for this process 
SPARK_MEM=${SPARK_MEM:-512m} 
export SPARK_MEM 

# Set JAVA_OPTS to be able to load native libraries and to set heap size 
JAVA_OPTS="$OUR_JAVA_OPTS" 
JAVA_OPTS="$JAVA_OPTS -Djava.library.path=$SPARK_LIBRARY_PATH" 
JAVA_OPTS="$JAVA_OPTS -Xms$SPARK_MEM -Xmx$SPARK_MEM" 

können Sie die Dokumentation here Skripte bereitstellen finden.

+0

Danke ~ Ich werde später versuchen. Von Funken Ui zeigt es die Erinnerung an jeden Executor ist 4096. Also die Einstellung wurde aktiviert, oder? – hequn8128

+0

Sah deine Antwort, während ich mit einem ähnlichen Problem konfrontiert bin (http://stackoverflow.com/questions/34762432/spark-ignores-spark-worker-memory). Wenn Sie auf den Link klicken, den Sie angegeben haben, sieht das so aus, als ob Xms/Xmx nicht mehr da ist. Können Sie mir sagen, warum? – Seffy

223

Ich habe ein paar Vorschläge:

  • Wenn die Knoten für Spark 6g maximal so konfiguriert sind, (und ein wenig für andere Prozesse zu verlassen), dann 6g verwenden, anstatt 4g, spark.executor.memory=6g. Stellen Sie sicher, Sie verwenden so viel Speicher wie möglich durch Überprüfen der Benutzeroberfläche (es wird sagen, wie viel Speicher Sie verwenden)
  • Versuchen Sie mit mehr Partitionen, sollten Sie 2 bis 4 pro CPU haben. IME erhöht die Anzahl der Partitionen ist oft der einfachste Weg, um ein Programm stabiler (und oft schneller) zu machen. Bei großen Datenmengen benötigen Sie möglicherweise weit mehr als 4 pro CPU. In einigen Fällen musste ich 8000 Partitionen verwenden.
  • Verringern Sie den Bruchteil des für die Zwischenspeicherung reservierten Speichers mit spark.storage.memoryFraction. Wenn Sie in Ihrem Code nicht oder persist verwenden, könnte dies auch 0 sein. Es ist standardmäßig 0,6, was bedeutet, dass Sie nur 0,4 * 4g Speicher für Ihren Heap erhalten. Ein IME, der den Mem-Frac reduziert, führt oft dazu, dass OOMs verschwinden. UPDATE: Von Funken 1.6 werden wir anscheinend nicht mehr mit diesen Werten spielen müssen, Funken werden sie automatisch bestimmen.
  • Ähnlich wie oben, aber Shuffle-Speicher-Fraktion. Wenn Ihr Job nicht viel Shuffle-Speicher benötigt, stellen Sie ihn auf einen niedrigeren Wert ein (dies kann dazu führen, dass Ihre Shuffle auf die Festplatte ausgelaufen sind, was sich auf die Geschwindigkeit nachteilig auswirken kann).Manchmal, wenn es eine Shuffle-Operation ist, die OOMing ist, müssen Sie das Gegenteil tun, d. H., Setzen Sie es auf etwas Großes, wie 0.8, oder stellen Sie sicher, dass Sie Ihre Shuffle auf die Festplatte verschütten (es ist der Standard seit 1.0.0).
  • Achten Sie auf Speicherlecks, diese werden oft durch versehentliches Schließen von Objekten verursacht, die Sie nicht in Ihren Lambdas benötigen. Die Art der Diagnose besteht darin, in den Protokollen auf die "serialisierte Aufgabe als XXX-Byte" zu achten. Wenn XXX größer als ein paar k oder mehr als ein MB ist, liegt möglicherweise ein Speicherleck vor. Siehe https://stackoverflow.com/a/25270600/1586965
  • Ähnlich wie oben; Verwenden Sie Broadcast-Variablen, wenn Sie wirklich große Objekte benötigen.
  • Wenn Sie große RDDs zwischenspeichern und einige Zugriffszeiten opfern, sollten Sie die RDD http://spark.apache.org/docs/latest/tuning.html#serialized-rdd-storage serialisieren. Oder sie sogar auf der Festplatte zwischenspeichern (was bei SSDs manchmal nicht so schlimm ist).
  • (Erweiterte) Im Zusammenhang mit oben vermeiden Sie String und stark verschachtelte Strukturen (wie Map und verschachtelte Fall Klassen). Wenn möglich, versuchen Sie, nur primitive Typen zu verwenden und alle Nicht-Primitiven zu indexieren, besonders wenn Sie viele Duplikate erwarten. Wählen Sie WrappedArray über verschachtelte Strukturen wann immer möglich. Oder führen Sie sogar Ihre eigene Serialisierung aus - Sie erhalten die meisten Informationen darüber, wie Sie Ihre Daten effizient in Bytes sichern können, USE IT!
  • (Bit Hacky) Auch wenn Caching, sollten Sie eine Dataset mit Ihrer Struktur cachen, wie es effizienter Serialisierung verwenden. Dies sollte als ein Hack im Vergleich zum vorherigen Aufzählungspunkt betrachtet werden. Wenn Sie Ihr Domänenwissen in Ihre Algo/Serialisierung einbauen, können Sie den Speicher-/Cache-Speicherplatz um 100x oder 1000x minimieren, während ein Dataset wahrscheinlich 2x bis 5x im Speicher und 10x komprimiert (Parkett) auf der Festplatte gibt.

http://spark.apache.org/docs/1.2.1/configuration.html

EDIT: (So kann ich google mich einfacher) Hier finden Sie auch ein Hinweis auf dieses Problem:

java.lang.OutOfMemoryError : GC overhead limit exceeded 
+0

Vielen Dank für Ihre Vorschläge ~ Wenn ich spark.executor.memory = 6g gesetzt habe, wird Spark das Problem haben: "Überprüfen Sie Ihre Cluster-Benutzeroberfläche, um sicherzustellen, dass die Mitarbeiter registriert sind und genügend Speicher haben". Das Setzen von spark.storage.memoryFraction auf 0.1 kann das Problem ebenfalls nicht lösen. Vielleicht liegt das Problem in meinem Code. Danke! – hequn8128

+0

@ hequn8128, Spark Executor Speicher muss passen Sie Funken Arbeiter Speicher –

+0

@samthebest Dies ist eine fantastische Antwort. Ich schätze die Protokollierungshilfe zum Auffinden von Speicherlecks sehr. –

0

Die Lage der Speicher Heap-Größe (zumindest in Funken zu setzen -1.0.0) ist in conf/funken-env. Die relevanten Variablen sind SPARK_EXECUTOR_MEMORY & SPARK_DRIVER_MEMORY. Weitere Dokumente sind in der deployment guide

Vergessen Sie auch nicht, die Konfigurationsdatei auf alle Slave-Knoten zu kopieren.

+2

Woher wissen Sie, welchen zwischen 'SPARK_EXECUTOR_MEMORY' und' SPARK_DRIVER_MEMORY' einzustellen ist? – Hunle

+5

, d. H. Welcher Fehler würde Ihnen sagen, die 'SPARK_EXECUTOR_MEMORY' zu erhöhen, und welcher Fehler würde Ihnen sagen,' SPARK_DRIVER_MEMORY' zu erhöhen? – Hunle

11

Sie sollten den Treiberspeicher erhöhen. In Ihrem $ SPARK_HOME/conf-Ordner sollten Sie die Datei spark-defaults.conf finden, bearbeiten und setzen Sie die spark.driver.memory 4000m abhängig von dem Speicher auf Ihrem Master, denke ich. Dies ist, was für mich das Problem behoben und alles läuft reibungslos

29

Um einen Anwendungsfall dazu hinzufügen, die oft nicht diskutiert wird, werde ich eine Lösung darstellen, wenn eine Spark Anwendung über spark-submit in lokalen Modus einreichen.

Nach dem gitbook Mastering Apache Spark von Jacek Laskowski:

You can run Spark in local mode. In this non-distributed single-JVM deployment mode, Spark spawns all the execution components - driver, executor, backend, and master - in the same JVM. This is the only mode where a driver is used for execution.

Wenn Sie also OOM Fehler mit dem heap erleben, genügt es, die driver-memory anstatt die executor-memory einzustellen. Hier

ein Beispiel:

spark-1.6.1/bin/spark-submit 
    --class "MyClass" 
    --driver-memory 12g 
    --master local[*] 
    target/scala-2.10/simple-project_2.10-1.0.jar 
Verwandte Themen