2016-07-05 10 views
15

Ho file csv con circa 5000 righe e 950 colonne. In primo luogo lo carico a dataframe:Apache Spark: StackOverflowError durante il tentativo di indicizzare colonne stringa

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

Dopo che cerco tutte le colonne di stringhe

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

e voglio indicizzarli. Per questo creo indicizzatori per ogni colonna stringa

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

e creo gasdotto

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

Ma quando cerco di trasformare il mio dataframe iniziale con questo gasdotto

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

ottengo StackOverflowError

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) 
... 

Cosa sto sbagliando? Grazie.

+2

È possibile fornire una traccia di eccezione completa? – sebszyller

+0

Quale versione di JDK stai usando? –

+0

Ho provato jdk 1.8.0_60 e 1.8.0_101. Qui traccia completa http://pastebin.com/g9MsNtDp – Evilnef

risposta

2

Sembra che abbia trovato il tipo di soluzione: utilizzare la scintilla 2.0. Precedentemente, ho usato 1.6.2 - era l'ultima versione al momento del rilascio. Ho provato ad usare la versione di anteprima di 2.0, ma c'è anche il problema riprodotto.

-3

The StackOverflowError in Java Quando una chiamata di funzione viene richiamata da un'applicazione Java, uno stack frame viene allocato nello stack di chiamate. Il frame dello stack contiene i parametri del metodo richiamato, i suoi parametri locali e l'indirizzo di ritorno del metodo. L'indirizzo di ritorno indica il punto di esecuzione da cui l'esecuzione del programma deve continuare dopo il ritorno del metodo richiamato. Se non c'è spazio per un nuovo stack frame, allora StackOverflowError viene lanciato da Java Virtual Machine (JVM). Il caso più comune che può esaurire lo stack di un'applicazione Java è la ricorsione. In ricorsione, un metodo si richiama durante la sua esecuzione. La ricorsione è considerata come una potente tecnica di programmazione generica, ma deve essere utilizzata con cautela, in modo da evitare l'eccezione StackOverflowError.

La possibile soluzione è 1. Per impostazione predefinita, Spark utilizza solo la memoria RDD serializzazione. provare con un'opzione persist su disco

2.per provare ad aumentare le dimensioni dello stack JVM del driver, aggiungendo qualcosa come -Xss5m alle opzioni del driver. E 'probabile che alcuni recursing sta accadendo quando si verifica i tipi di colonna nella data.schema

--driver-java-opzioni "-Xss 100M"

se possibile condividere il file e completa traccia eccezione.

3

Molto probabilmente non c'è abbastanza memoria per conservare tutti i frame dello stack. Esperienza qualcosa di simile quando addestrato RandomForestModel. La soluzione che funziona per me è è quello di eseguire la mia applicazione driver (che è il servizio web) con parametri aggiuntivi: si prevede

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

In realtà sto affrontando lo stesso problema, come posso scoprire la dimensione dello stack predefinita? Inoltre, vedo che sta aumentando la dimensione dello stack per l'esecutore, non il driver, è corretto? –

+0

@ h.z. È per entrambi, perché entrambe le parti stanno lavorando insieme. ThreadStackSize è per il driver. Il per gli esecutori va da executor.extraJavaOptions. Non sono sicuro che sia possibile misurare le dimensioni, ho solo aumentato il mio fino a quando non ha iniziato a funzionare. Presumo che per un set di dati ancora più grande fallirebbe ancora. – evgenii

Problemi correlati