Spark java.lang.OutOfMemoryError:Java堆空间

时间:2018-06-28 11:44:54

标签: apache-spark out-of-memory spark-submit

使用spark运行模型训练管道时出现上述错误

`val inputData = spark.read
  .option("header", true)
  .option("mode","DROPMALFORMED")
  .csv(input)
  .repartition(500)
  .toDF("b", "c")
  .withColumn("b", lower(col("b")))
  .withColumn("c", lower(col("c")))
  .toDF("b", "c")
  .na.drop()`

inputData 大约有2500万行,大小约为2gb。模型建立阶段就是这样

val tokenizer = new Tokenizer()
  .setInputCol("c")
  .setOutputCol("tokens")

val cvSpec = new CountVectorizer()
  .setInputCol("tokens")
  .setOutputCol("features")
  .setMinDF(minDF)
  .setVocabSize(vocabSize)

val nb = new NaiveBayes()
  .setLabelCol("bi")
  .setFeaturesCol("features")
  .setPredictionCol("prediction")
  .setSmoothing(smoothing)

new Pipeline().setStages(Array(tokenizer, cvSpec, nb)).fit(inputData)

我正在使用以下命令在具有16gb RAM的计算机中本地运行上述spark作业

spark-submit --class holmes.model.building.ModelBuilder ./holmes-model-building/target/scala-2.11/holmes-model-building_2.11-1.0.0-SNAPSHOT-7d6978.jar --master local[*] --conf spark.serializer=org.apache.spark.serializer.KryoSerializer --conf spark.kryoserializer.buffer.max=2000m --conf spark.driver.maxResultSize=2g --conf spark.rpc.message.maxSize=1024 --conf spark.memory.offHeap.enabled=true --conf spark.memory.offHeap.size=50g --driver-memory=12g

oom错误是由(在堆栈跟踪的底部)触发的         通过org.apache.spark.util.collection.ExternalSorter.writePartitionedFile(ExternalSorter.scala:706)

日志:

Caused by: java.lang.OutOfMemoryError: Java heap space at java.lang.reflect.Array.newInstance(Array.java:75) at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1897) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1529) java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2027) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1535) org.apache.spark.util.collection.ExternalSorter.writePartitionedFile(ExternalSorter.scala:706) 

任何建议都会很棒:)

2 个答案:

答案 0 :(得分:1)

我会尝试的事情:

1)删除b,并将驱动程序内存增加到包装盒上可用内存的90%。您可能意识到了这一点,因为您没有设置执行程序内存,但是在本地模式下,驱动程序和执行程序都在同一进程中运行,该进程由驱动程序内存控制。我没有尝试过,但是spark.memory.offHeap.enabled=true功能听起来价值有限。 Reference

2)实际集群而不是本地模式。显然,更多节点将为您提供更多RAM。

3a)如果要坚持使用本地模式,请尝试使用更少的内核。您可以通过指定要在主设置(例如offHeap)中使用的内核数来代替使用所有内核的--master local[4],来做到这一点。以更少的线程运行同时处理数据将在任何给定时间导致RAM中的数据更少。

3b)如果移至群集,则出于与上述相同的原因,您可能还想调整执行程序核心的数量。您可以使用local[*]标志来实现。

4)尝试使用更多分区。在示例代码中,您已重新分区为500个分区,也许尝试1000或2000?分区越多,意味着每个分区越小,内存压力越小。

答案 1 :(得分:0)

通常,当Java堆中没有足够的空间来分配对象时,将引发此错误。在这种情况下,垃圾收集器无法提供空间来容纳新对象,并且堆无法进一步扩展。另外,当本机内存不足以支持Java类的加载时,可能会引发此错误。在极少数情况下,如果花费大量时间进行垃圾回收并且释放了很少的内存,则可能引发java.lang.OutOfMemoryError。

如何解决错误:

How to set Apache Spark Executor memory

Spark java.lang.OutOfMemoryError: Java heap space