增加spark.executor.cores会更快地进行洗牌

时间:2016-11-19 04:24:47

标签: apache-spark

假设我们修复了spark作业的核心总数和总内存大小,并且输入数据中有很多分区。比较这两种配置:

  • 100个执行者,10G内存和每个执行者1个核心
  • 20个执行器,50G内存和每个执行器5个内核

这是我的问题:

  1. 有时我发现NODE_LOCAL任务从网络而不是内存/磁盘获取输入,它实际上是指同一台机器上两个执行程序进程之间的通信吗?
  2. 如果1为真,那么第二个会更快,因为改组可以更“处理本地”吗?
  3. 如果只有地图任务,第二个会和第一个任务一样快吗?
  4. 我可以说#executor cores和{{1}}之间的主要权衡是IO吗?
  5. 由于

2 个答案:

答案 0 :(得分:2)

<强> Q1。有时我发现NODE_LOCAL任务从网络而不是内存/磁盘获取输入,它实际上是指同一台机器上两个执行程序进程之间的通信吗?

NODE_LOCAL任务可能从同一节点中的其他执行程序获取输入,或者需要从HDFS,缓存等系统中检索。是,NODE_LOCAL任务表示同一节点中两个执行程序进程之间的通信。 RACK_LOCAL表示数据位于另一个节点,因此需要在执行前进行传输。

问2.如果1为真,那么第二个会更快,因为改组可以更多&#34;处理本地&#34;?

  • 100个执行者,10G内存和每个执行者1个核心
  • 20个执行器,50G内存和每个执行器5个内核

    1是正确的,但决定哪个选项更快取决于几个因素(#of executors vs #of executor-cores)。

Spark-submit 内存参数,例如&#34;执行者数量&#34;和#34;执行者核心数量&#34;属性会影响Spark可以缓存的数据量,以及用于分组,聚合和连接的shuffle数据结构的最大大小。具有太多内存的运行执行程序通常会导致过多的垃圾收集延迟。

cores属性控制执行程序可以运行的并发任务数。据观察,每个执行程序有五个任务可以实现完全写入吞吐量。每个执行程序的大量核心导致 HDFS I / O吞吐量,从而大大降低了应用程序的速度。

运行具有单核和更少内存的执行程序会丢弃在单个JVM中运行多个任务所带来的好处。例如,广播变量需要在每个执行器上复制一次,因此许多小执行器将导致更多的数据副本。

要优化Spark的内存消耗,请确定数据集需要多少内存。为此,您可以创建DataFrame,对其进行缓存并在Spark UI的“存储”选项卡中检查数据集大小。基于数据集大小以及您可以获得最佳执行者数量的操作类型。芯

另外 - 您可以通过使用spark.dynamicAllocation.enabled属性启用动态分配来避免设置所有这些内存属性。动态分配使Spark应用程序能够在存在待处理任务的积压和释放时请求执行程序空闲时执行者。

<强> Q3。如果只有地图任务,第二个任务是否与第一个任务一样快?

可能是的。根据Cloudera的建议。第二个选项优于第一个选项,但它取决于数据集大小。

问4.我可以说#executor和#executor核心之间的主要权衡是IO吗?

不确定这一点,但建议拥有与数据节点一样多的执行程序,以及从群集中获得的核心数量。

答案 1 :(得分:1)

问4.我可以说#executor和#executor核心之间的主要权衡是IO吗?

主要的权衡是内存管理和IO。如果您使用简单的映射运行一些简单的多阶段DAG并减少,您将在spark历史中看到4个具有2个核心的节点将同时处理与具有8个核心的1个节点并行的任务。在阶段开始时,每个初始任务加载都会发生反序列化。

最大的区别在于内存开销减少。在具有大量内存的现代服务器中,这不是一个大问题。

由于线程调度程序中的性能下降曲线,您会很难找到有人为执行程序推荐超过5个内核的人。

启动集群/执行程序大小调整的一个好的经验法则如下:

(ceiling(total_host_physical_cores * 1.15) - 2)/ executor.cores = 每个主机的执行者数量

executor.cores = 2 开始是一个不错的选择。

每个遗嘱执行人的记忆更多地是关于您的DAG和您的摄取大小。