2016-07-05 9 views
15

Ich habe eine CSV-Datei mit etwa 5000 Zeilen und 950 Spalten. Zuerst habe ich es zu Datenframe laden:Apache Spark: StackOverflowError beim Versuch, String-Spalten zu indexieren

val data = sqlContext.read 
    .format(csvFormat) 
    .option("header", "true") 
    .option("inferSchema", "true") 
    .load(file) 
    .cache() 

Danach habe ich alle Spalten Zeichenfolge suchen

val featuresToIndex = data.schema 
    .filter(_.dataType == StringType) 
    .map(field => field.name) 

und wollen, dass sie zu indizieren. Dafür habe ich erstellen Indexer für jede Saite Spalte

val stringIndexers = featuresToIndex.map(colName => 
    new StringIndexer() 
    .setInputCol(colName) 
    .setOutputCol(colName + "Indexed")) 

und erstellen Pipeline

val pipeline = new Pipeline().setStages(stringIndexers.toArray) 

Aber wenn ich versuche, meinen ersten Datenrahmen mit dieser Pipeline

val indexedDf = pipeline.fit(data).transform(data) 

ich Stackoverflow

erhalten zu transformieren
16/07/05 16:55:12 INFO DAGScheduler: Job 4 finished: countByValue at StringIndexer.scala:86, took 7.882774 s 
Exception in thread "main" java.lang.StackOverflowError 
at scala.collection.immutable.Set$Set1.contains(Set.scala:84) 
at scala.collection.immutable.Set$Set1.$plus(Set.scala:86) 
at scala.collection.immutable.Set$Set1.$plus(Set.scala:81) 
at scala.collection.mutable.SetBuilder.$plus$eq(SetBuilder.scala:22) 
at scala.collection.mutable.SetBuilder.$plus$eq(SetBuilder.scala:20) 
at scala.collection.generic.Growable$class.loop$1(Growable.scala:53) 
at scala.collection.generic.Growable$class.$plus$plus$eq(Growable.scala:57) 
at scala.collection.mutable.SetBuilder.$plus$plus$eq(SetBuilder.scala:20) 
at scala.collection.TraversableLike$class.to(TraversableLike.scala:590) 
at scala.collection.AbstractTraversable.to(Traversable.scala:104) 
at scala.collection.TraversableOnce$class.toSet(TraversableOnce.scala:304) 
at scala.collection.AbstractTraversable.toSet(Traversable.scala:104) 
at org.apache.spark.sql.catalyst.trees.TreeNode.containsChild$lzycompute(TreeNode.scala:86) 
at org.apache.spark.sql.catalyst.trees.TreeNode.containsChild(TreeNode.scala:86) 
at org.apache.spark.sql.catalyst.trees.TreeNode$$anonfun$4.apply(TreeNode.scala:280) 
at scala.collection.Iterator$$anon$11.next(Iterator.scala:409) 
... 

Was mache ich falsch? Danke.

+2

Können Sie eine vollständige Ablaufverfolgung für Ausnahmen bereitstellen? – sebszyller

+0

Welche Version von JDK verwenden Sie? –

+0

Ich versuchte jdk 1.8.0_60 und 1.8.0_101. Hier vollständige Ablaufverfolgung http://pastebin.com/g9MsNtDp – Evilnef

Antwort

2

Scheint wie ich die Art der Lösung gefunden - verwenden Sie Funken 2.0. Zuvor verwendete ich 1.6.2 - es war die neueste Version zum Zeitpunkt der Ausgabe. Ich habe versucht, die Preview-Version von 2.0 zu verwenden, aber da ist auch das Problem reproduziert.

-3

Der StackOverflowError in Java Wenn ein Funktionsaufruf von einer Java-Anwendung aufgerufen wird, wird ein Stack-Frame auf dem Aufruf-Stack zugeordnet. Der Stack-Frame enthält die Parameter der aufgerufenen Methode, ihre lokalen Parameter und die Rückgabeadresse der Methode. Die Rücksprungadresse bezeichnet den Ausführungspunkt, von dem die Programmausführung fortgesetzt werden soll, nachdem die aufgerufene Methode zurückgegeben wurde. Wenn kein Platz für einen neuen Stapelrahmen vorhanden ist, wird StackOverflowError von der Java Virtual Machine (JVM) ausgelöst. Der häufigste Fall, bei dem der Stack einer Java-Anwendung erschöpft sein kann, ist Rekursion. Bei der Rekursion ruft sich eine Methode während ihrer Ausführung selbst auf. Rekursion wird als eine leistungsfähige Allzweck-Programmiertechnik betrachtet, muss aber mit Vorsicht verwendet werden, damit StackOverflowError vermieden werden kann.

Die mögliche Lösung ist 1. Standardmäßig verwendet Spark Speicher nur RDD Serialisierung. versuchen Sie es mit einer persistieren auf Festplatte Option

2. versuchen, die JVM-Stack-Größe des Treibers zu erhöhen, etwas wie -Xss5m zu den Treiberoptionen hinzufügen. Es ist wahrscheinlich, dass einige recursing geschieht, wenn Sie die Spaltentypen in der data.schema

--driver-java-Optionen „-Xss 100M“

wenn möglich Anteil der Datei und vollständige Ausnahme Spur einlagern möchten.

3

Wahrscheinlich gibt es nicht genug Speicher, um alle Stack-Frames zu speichern. Ich erlebe etwas ähnliches, wenn ich RandomForestModel trainiere. Die Abhilfe, die für mich funktioniert, ist zu meinem Fahrer Anwendung ausführen (das ist Web-Service) mit zusätzlichen Parametern:

-XX:ThreadStackSize=81920 -Dspark.executor.extraJavaOptions='-XX:ThreadStackSize=81920' 
+0

Ich bin tatsächlich mit dem gleichen Problem konfrontiert, wie kann ich die Standard-Stack-Größe herausfinden? Außerdem sehe ich, dass es die Stack-Größe für den Executor erhöht, nicht der Treiber, ist das korrekt? –

+0

@ h.z. Es ist für beide, weil beide Parteien zusammenarbeiten. ThreadStackSize ist für den Treiber. Der für Executors geht von executor.extraJavaOptions. Ich bin mir nicht sicher, ob es möglich ist, die Größe zu messen, ich habe nur meine erhöht, bis es zu arbeiten begann. Ich nehme an, für noch größere Datenmengen würde es immer noch scheitern. – evgenii

Verwandte Themen