繁体   English   中英

作业运行成功时,驱动程序内存,执行程序内存,驱动程序内存开销和执行程序内存开销的Apache Spark效果

[英]Apache Spark Effects of Driver Memory, Executor Memory, Driver Memory Overhead and Executor Memory Overhead on success of job runs

我正在对YARN上的Spark作业进行一些内存调整,我注意到不同的设置会产生不同的结果并影响Spark作业运行的结果。 但是,我很困惑,并不完全理解为什么会发生这种情况,如果有人可以提供一些指导和解释,我会很感激。

我将提供一些背景信息并发布我的问题,并描述我之后经历过的案例。

我的环境设置如下:

  • 内存20G,每个节点20个VCores(总共3个节点)
  • Hadoop 2.6.0
  • Spark 1.4.0

我的代码递归地过滤RDD以使其变小(将示例作为算法的一部分移除),然后执行mapToPair并收集以收集结果并将其保存在列表中。

问题

  1. 为什么抛出不同的错误并且第一个和第二个案例之间的作业运行时间更长(第二种情况)只有执行程序内存增加了? 这两个错误是否以某种方式相关联?

  2. 第三和第四种情况都成功了,我明白这是因为我提供了更多的内存来解决内存问题。 但是,在第三种情况下,

spark.driver.memory + spark.yarn.driver.memoryOverhead = YARN将创建JVM的内存

= 11g +(driverMemory * 0.07,最小值为384m)= 11g + 1.154g = 12.154g

所以,根据公式,我可以看到我的工作需要大约12.154g的MEMORY_TOTAL才能成功运行,这解释了为什么我需要超过10g的驱动程序内存设置。

但对于第四种情况,

spark.driver.memory + spark.yarn.driver.memoryOverhead = YARN将创建JVM的内存

= 2 +(driverMemory * 0.07,最小值为384m)= 2g + 0.524g = 2.524g

似乎只需将内存开销增加少量的1024(1g),就可以成功运行作业,驱动程序内存仅为2g,而MEMORY_TOTAL仅为2.524g 而没有开销配置,驱动程序内存小于11g会失败,但从公式中没有意义,这就是为什么我感到困惑。

为什么增加内存开销(对于驱动程序和执行程序)允许我的作业以较低的MEMORY_TOTAL(12.154g vs 2.524g)成功完成? 在这里有一些其他内部事物在我失踪吗?

第一个案例

/bin/spark-submit --class <class name> --master yarn-cluster --driver-memory 7g --executor-memory 1g --num-executors 3 --executor-cores 1 --jars <jar file>

如果我用任何小于11g的驱动程序内存运行我的程序,我将得到下面的错误,即停止的SparkContext或类似的错误,这是在停止的SparkContext上调用的方法。 从我收集的内容来看,这与记忆力不足有关。

DriverMemory-7g_ExecutorMemory-1G

第二个案例

/bin/spark-submit --class <class name> --master yarn-cluster --driver-memory 7g --executor-memory 3g --num-executors 3 --executor-cores 1 --jars <jar file>

如果我运行具有相同驱动程序内存但执行程序内存较高的程序,则作业比第一种情况运行时间更长(约3-4分钟),然后它将遇到与先前不同的错误,这是一个请求/使用更多内存的容器允许并因此而被杀害。 虽然我发现它很奇怪,因为执行程序内存增加了,并且在第一种情况下发生了此错误而不是错误。

DriverMemory-7g_ExecutorMemory-3G

第三个案例

/bin/spark-submit --class <class name> --master yarn-cluster --driver-memory 11g --executor-memory 1g --num-executors 3 --executor-cores 1 --jars <jar file>

驱动程序内存大于10g的任何设置都将导致作业能够成功运行。

第四个案例

/bin/spark-submit --class <class name> --master yarn-cluster --driver-memory 2g --executor-memory 1g --conf spark.yarn.executor.memoryOverhead=1024 --conf spark.yarn.driver.memoryOverhead=1024 --num-executors 3 --executor-cores 1 --jars <jar file>

使用此设置将成功运行作业(驱动程序内存2g和执行程序内存1g,但会增加驱动程序内存开销(1g)和执行程序内存开销(1g)。

任何帮助将不胜感激,并将真正帮助我理解Spark。 提前致谢。

所有案例都使用

--executor-cores 1

这是最好的做法,超过1.并且不要超过5.从我们的经验和Spark开发人员的推荐。

例如http://blog.cloudera.com/blog/2015/03/how-to-tune-your-apache-spark-jobs-part-2/

A rough guess is that at most five tasks per executor 
can achieve full write throughput, so it’s good to keep 
the number of cores per executor below that number

我现在找不到参考建议每个执行者超过1个核心的地方。 但是这个想法是在同一个执行器中运行多个任务使您能够共享一些公共内存区域,从而实际上节省了内存。

从--executor-cores 2开始,双--executor-memory(因为--executor-cores还告诉一个执行程序将运行多少个任务),并看看它为你做了什么。 您的环境在可用内存方面是紧凑的,因此转到3或4将为您提供更好的内存利用率。

我们使用Spark 1.5并且很久以前停止使用--executor-cores 1,因为它给出了GC问题; 它看起来也像是一个Spark bug,因为只是提供更多的内存并没有帮助,只需要切换到每个容器有更多的任务。 我想同一个执行程序中的任务可能会在不同的时间达到内存消耗的高峰,所以你不要浪费/不必为了使它工作而过度配置内存。

另一个好处是Spark的共享变量(累加器和广播变量)每个执行器只有一个副本,而不是每个任务 - 所以每个执行器切换到多个任务就是直接节省内存。 即使您没有显式使用Spark共享变量,Spark也很可能在内部创建它们。 例如,如果您通过Spark SQL连接两个表,Spark的CBO可能决定广播较小的表(或较小的数据帧)以使连接运行更快。

http://spark.apache.org/docs/latest/programming-guide.html#shared-variables

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM