首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何调整spark executor数量、内核和executor内存?

如何调整spark executor数量、内核和executor内存?
EN

Stack Overflow用户
提问于 2016-06-17 08:03:13
回答 2查看 95K关注 0票数 99

你从哪里开始调整上面提到的参数。我们是从执行器内存开始,获得执行器数量,还是从核心开始,获得执行器数量。我跟踪了link。然而,得到了一个高层次的想法,但仍然不确定如何或从哪里开始并得出最终结论。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-06-17 08:03:13

下面的答案涵盖了标题中提到的3个主要方面-执行器数量、执行器内存和内核数量。可能还有其他参数,如驱动程序内存和其他参数,我在回答时还没有解决这些问题,但希望在不久的将来添加。

案例1硬件-6个节点,每个节点16个核心,64 GB内存

每个executor都是一个JVM实例。因此,我们可以在单个节点中拥有多个执行器

操作系统和Hadoop守护程序需要前1个核心和1 GB,因此可用15个核心,每个节点63 GB RAM

从如何选择内核数量开始

代码语言:javascript
复制
Number of cores = Concurrent tasks as executor can run 

So we might think, more concurrent tasks for each executor will give better performance. But research shows that
any application with more than 5 concurrent tasks, would lead to bad show. So stick this to 5.

This number came from the ability of executor and not from how many cores a system has. So the number 5 stays same
even if you have double(32) cores in the CPU.

遗嘱执行人数量:

代码语言:javascript
复制
Coming back to next step, with 5 as cores per executor, and 15 as total available cores in one Node(CPU) - we come to 
3 executors per node.

So with 6 nodes, and 3 executors per node - we get 18 executors. Out of 18 we need 1 executor (java process) for AM in YARN we get 17 executors

This 17 is the number we give to spark using --num-executors while running from spark-submit shell command

每个执行器的内存:

代码语言:javascript
复制
From above step, we have 3 executors  per node. And available RAM is 63 GB

So memory for each executor is 63/3 = 21GB. 

However small overhead memory is also needed to determine the full memory request to YARN for each executor.
Formula for that over head is max(384, .07 * spark.executor.memory)

Calculating that overhead - .07 * 21 (Here 21 is calculated as above 63/3)
                            = 1.47

Since 1.47 GB > 384 MB, the over head is 1.47.
Take the above from each 21 above => 21 - 1.47 ~ 19 GB

So executor memory - 19 GB

最终数字-执行器- 17个,核心5个,执行器内存- 19 GB

案例2硬件:相同的6节点、32核、64 GB

对于良好的并发性,5是相同的

每个节点的执行器数量= 32/5 ~6

所以总共执行者=6*6个节点= 36。当AM = 35时,最终数字为36 -1

Executor内存为:每个节点6个Executor。63/6 ~ 10。开销为.07 * 10 =700MB。因此,舍入到1 GB作为开销,我们得到10-1 =9 GB

最终数字-执行器- 35个,核心5个,执行器内存-9 GB

案例3

上面的场景首先接受固定数量的内核,然后移动到# of executors and memory。

现在,对于第一种情况,如果我们认为我们不需要19 GB,并且只需要10 GB就足够了,那么下面是数字:

每个节点的执行器的核心数为5=3

在这个阶段,这将导致21,然后根据我们的第一次计算,19。但既然我们认为10就可以了(假设开销很小),那么我们就不能将每个节点的执行器数量切换到6(比如63/10)。因为每个节点有6个执行器和5个核心,所以当我们只有16个核心时,每个节点就变成了30个核心。因此,我们还需要更改每个执行器的核心数量。

所以再算一遍,

幻数5等于3(任何小于或等于5的数字)。因此,如果有3个核心和15个可用核心,那么每个节点就会有5个执行器。So (5*6 -1) = 29个执行者

内存是63/5 ~ 12。开销是12*.07=.84,所以执行器内存是12 -1 GB = 11 GB

最终的数字是29个执行器,3个核心,执行器内存是11 GB

动态分配:

注:如果启用了动态分配,则为执行者数量的上限。这就是说,如果需要的话,spark应用程序可以吃掉所有资源。因此,在您有其他应用程序正在运行的集群中,它们也需要内核来运行任务,请确保您在集群级别执行此操作。我的意思是,您可以根据用户访问权限为纱线分配特定数量的内核。因此,您可以创建spark_user,然后为该用户分配内核(最小/最大)。这些限制是为了在spark和其他在纱线上运行的应用程序之间共享。

spark.dynamicAllocation.enabled -当它被设置为true时-我们不需要提到executors。原因如下:

我们在spark-submit中给出的静态参数数是整个作业持续时间的。然而,如果动态分配进入画面,将有不同的阶段,如

开始:

初始执行者数量(spark.dynamicAllocation.initialExecutors)

数量:

然后根据负载(待处理的任务)请求多少。这最终将是我们在spark-submit以静态方式给出的数字。因此,一旦设置了初始的执行器编号,我们就转到最小(spark.dynamicAllocation.minExecutors)和最大(spark.dynamicAllocation.maxExecutors)编号。

何时要求或给予:

我们什么时候请求新的执行器(spark.dynamicAllocation.schedulerBacklogTimeout) --在这么长的时间内都有未完成的任务。所以请求吧。每一轮请求的执行者数量比前一轮成倍增加。例如,应用程序将在第一轮中添加1个executor,然后在随后的几轮中添加2、4、8个executor,依此类推。在特定的点上,上述最大值出现在画面中。

我们什么时候送出一个遗嘱执行人(spark.dynamicAllocation.executorIdleTimeout) -

如果我遗漏了什么,请纠正我。以上是我基于我所分享的博客和一些在线资源的理解。谢谢。

参考:

  • http://site.clairvoyantsoft.com/understanding-resource-allocation-configurations-spark-application/
  • http://spark.apache.org/docs/latest/configuration.html#dynamic-allocation
  • http://spark.apache.org/docs/latest/job-scheduling.html#resource-allocation-policy
票数 233
EN

Stack Overflow用户

发布于 2017-04-07 18:46:17

此外,这取决于您的用例,一个重要的配置参数是:

来自http://spark.apache.org/docs/latest/configuration.html#memory-managementspark.memory.fraction(用于执行和存储的(堆空间- 300MB)的一部分)。

如果你不使用缓存/持久化,将它设置为0.1,这样你的程序就有了所有的内存。

如果您使用缓存/持久化,您可以通过以下方式检查占用的内存:

代码语言:javascript
复制
sc.getExecutorMemoryStatus.map(a => (a._2._1 - a._2._2)/(1024.0*1024*1024)).sum

您是从HDFS还是从HTTP读取数据?

同样,调优取决于您的用例。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37871194

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档