我的集群:1个主节点,11个从节点,每个节点有6gb内存。

我的设置:

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

问题是这样的:

首先,我从HDFS读取一些数据(2.19 GB)到RDD:

val imageBundleRDD = sc.newAPIHadoopFile(...)

其次,在这个RDD上做一些事情:

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

最后,输出到HDFS:

res.saveAsNewAPIHadoopFile(...)

当我运行我的程序时,它显示:

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

任务太多?

PS:当输入数据约为225 MB时,一切正常。

我该如何解决这个问题呢?


当前回答

你应该配置offHeap内存设置如下所示:

val spark = SparkSession
     .builder()
     .master("local[*]")
     .config("spark.executor.memory", "70g")
     .config("spark.driver.memory", "50g")
     .config("spark.memory.offHeap.enabled",true)
     .config("spark.memory.offHeap.size","16g")   
     .appName("sampleCodeForReference")
     .getOrCreate()

根据您机器的RAM可用性提供驱动程序内存和执行程序内存。如果仍然面临OutofMemory问题,可以增加offHeap大小。

其他回答

简单,如果你正在使用一个脚本或juyter笔记本,然后只设置配置路径,当你开始构建一个spark会话…

spark = SparkSession.builder.master('local[*]').config("spark.driver.memory", "15g").appName('testing').getOrCreate()

堆空间错误通常是由于将太多数据带回驱动程序或执行程序而发生的。 在您的代码中,似乎没有将任何东西带回驱动程序,相反,您可能重载了使用threeDReconstruction()方法将一个输入记录/行映射到另一个输入记录/行的执行器。我不确定在方法定义中是什么,但这肯定会导致执行器的重载。 现在你有两个选择,

编辑你的代码,以更有效的方式进行三维重建。 不要编辑代码,但是给你的执行程序更多的内存,以及更多的内存开销。[spark.executor。内存或spark.driver.memoryOverhead]

我建议谨慎使用,只使用你需要的量。就内存需求而言,每个作业都是独一无二的,所以我建议根据经验尝试不同的值,每次增加2的幂(256M,512M,1G ..)等等)

您将得到一个可以工作的执行程序内存的值。尝试使用此值重新运行作业3或5次,然后再接受此配置。

对于上面提到的错误,我没有什么建议。

检查执行程序分配的内存可能必须处理需要比分配的内存更多的分区。

尝试查看是否有更多的shuffle是实时的,因为shuffle是昂贵的操作,因为它们涉及磁盘I/O、数据序列化和网络I/O

●使用广播连接

避免使用groupByKeys,尽量用ReduceByKey代替

●避免在任何发生洗牌的地方使用巨大的Java对象

根据我对上面提供的代码的理解,它加载文件并进行映射操作并保存回来。没有需要shuffle的操作。此外,没有任何操作需要将数据传输到驱动程序,因此调优与shuffle或驱动程序相关的任何内容都不会产生影响。当任务太多时,驱动程序确实会有问题,但这只是在spark 2.0.2版本之前。可能会有两件事出错。

There are only one or a few executors. Increase the number of executors so that they can be allocated to different slaves. If you are using yarn need to change num-executors config or if you are using spark standalone then need to tune num cores per executor and spark max cores conf. In standalone num executors = max cores / cores per executor . The number of partitions are very few or maybe only one. So if this is low even if we have multi-cores,multi executors it will not be of much help as parallelization is dependent on the number of partitions. So increase the partitions by doing imageBundleRDD.repartition(11)

设置内存堆大小的位置(至少在spark-1.0.0中)在conf/spark-env中。 相关变量为SPARK_EXECUTOR_MEMORY和SPARK_DRIVER_MEMORY。 部署指南中有更多的文档

此外,不要忘记将配置文件复制到所有从节点。