Apache Spark:尝试索引字符串列时出现StackOverflowError

时间:2016-07-05 14:34:19

标签: java scala apache-spark apache-spark-mllib

我有大约5000行和950列的csv文件。首先,我将其加载到DataFrame:

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

之后我搜索所有字符串列

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

并想要将它们编入索引。为此我为每个字符串列创建索引器

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

并创建管道

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

但是当我尝试用这个管道转换我的初始数据帧时

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

我得到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)
...

我做错了什么? 感谢。

3 个答案:

答案 0 :(得分:5)

最有可能的是没有足够的内存来保留所有堆栈帧。我在训练的RandomForestModel时遇到类似的东西。适用于我的解决方法是使用其他参数运行我的驱动程序应用程序(即Web服务):

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

答案 1 :(得分:-2)

预计会出现StackOverflowError错误。我们需要阻止代码创建溢出。检查以下与相同错误相关的问题和答案。

Spark java.lang.StackOverflowError

Spark gives a StackOverflowError when training using ALS

希望以上链接能帮到你..

答案 2 :(得分:-3)

Java中的StackOverflowError 当Java应用程序调用函数调用时,会在调用堆栈上分配堆栈帧。堆栈帧包含调用方法的参数,其本地参数以及方法的返回地址。返回地址表示执行点,程序执行将在调用方法返回后继续执行。如果没有新堆栈帧的空间,则Java虚拟机(JVM)将抛出StackOverflowError。 可能耗尽Java应用程序堆栈的最常见情况是递归。在递归中,方法在执行期间调用自身。递归被认为是一种强大的通用编程技术,但必须谨慎使用,以避免出现StackOverflowError。

可能的解决方案是 1.默认情况下,Spark仅使用内存RDD序列化。尝试使用磁盘上的持久性选项

2.尝试增加驱动程序的JVM堆栈大小,向驱动程序选项添加类似-Xss5m的内容。当您检查data.schema

中的列类型时,可能会发生一些递归

- driver-java-options" -Xss 100M"

如果可能,共享文件并完成异常跟踪。