Spark任务内存分配

6
我正在尝试找到最佳方式来配置我的群集节点上的内存。然而,我认为需要进一步了解一些事情,例如spark如何跨任务处理内存等内容。
例如,假设我有3个执行器,每个执行器可以并行运行8个任务(即8个核心)。如果我有一个具有24个分区的RDD,则理论上所有分区都可以并行处理。但是,如果我们在这里放大一个执行器,这意味着每个任务都可以在内存中拥有其分区进行操作。如果没有,则意味着无法并行处理8个任务,需要进行一些调度。
因此,我得出结论,要实现真正的并行性,了解分区大小的一些想法将会有所帮助,因为这将告诉您如何调整执行器以实现真正的并行性。
  • Q0-我只是想更好地了解一下,当一个执行器的内存不能容纳所有分区时会发生什么?有些分区会溢出到磁盘,而其他分区则在内存中进行操作吗?Spark是否为每个任务保留内存,如果检测到不足,是否安排任务?还是只会运行内存耗尽的错误?

  • Q1- executor内部的真正并行取决于执行器上可用的内存量吗?换句话说,我可能在群集中有8个核心,但如果我没有足够的内存一次加载8个分区的数据,则无法完全并行。

最后,我多次看到以下声明,但有些困惑:

“增加分区的数量也有助于减少内存不足错误,因为这意味着Spark将对每个执行器的较小子集进行操作。”

这究竟是如何工作的呢?我的意思是,Spark可能会处理更小的子集,但如果总的分区集无论如何都无法容纳内存,会发生什么?
1个回答

8

为什么要增加任务数量(分区)?

首先,我想回答让您感到困惑的最后一个问题。以下是来自另一个问题的引用:

Spark不需要将所有数据加载到内存中才能处理它。这是因为Spark会将数据分区成较小的块并分别处理。

事实上,默认情况下,Spark尝试将输入数据自动拆分为一些最优分区:

Spark会根据文件大小自动设置要在每个文件上运行的“map”任务数。

可以指定正在执行的操作的分区数(例如对于: def cogroup [W](other:RDD [(K,W)],numPartitions:Int)),并且在任何RDD转换之后进行.repartition()

此外,在文档的同一段落中,他们还说:

通常,我们建议在集群中的每个CPU核心上运行2-3个任务。

总而言之

  1. 默认分区数是一个很好的起点;
  2. 通常建议每个CPU使用2-3个分区。

Spark如何处理内存不足的输入?

简而言之,通过对输入和中间结果(RDD)进行分区。通常,每个小块都适合执行器可用的内存,并且可以快速处理。

Spark能够缓存计算过的RDD。默认情况下,每当RDD被重复使用时,它将被重新计算(未缓存);调用.cache().persist()可帮助在内存或磁盘上保持已经计算的结果。

内部每个执行器都有一个内存池,在执行和存储之间浮动(有关详细信息,请参见此处)。当任务执行时没有足够的内存时,Spark首先尝试清除一些存储缓存,然后将任务数据溢出到磁盘上。有关更多详细信息,请参见这些幻灯片。在这篇博客文章中,介绍了执行器和存储内存之间的平衡,并提供了漂亮的插图:

Spark memory allocation

内存溢出通常并不是由于大数据量直接引起的,而是由于拆分不当导致的大型辅助数据结构(例如Reducer上的HashMap)。因此,OutOfMemory不会仅因为输入数据太大而发生,但它可能会处理得非常缓慢(因为必须从磁盘读取/写入)。文档建议在Reducer上使用比执行器更多的分区。此外,他们建议对于Spark,200ms(运行时间)左右的任务大小是可以接受的。

概述:适当地拆分您的数据:每个核心超过1个分区,每个任务的运行时间应> 200毫秒。默认分区是一个很好的起点,可以手动调整参数。

(我建议在1/8集群上使用1/8输入数据子集来找到最佳分区数。)

同一执行程序中的任务是否会相互影响?

简短回答:他们会。更多详情请查看我上面提到的幻灯片(从第32张幻灯片开始)。

所有N个任务都会获得可用内存的第N部分,因此会影响彼此的“并行性”。如果我正确理解了您对真正的并行性的想法,那就是“充分利用CPU资源”。在这种情况下,是的,小内存池将导致数据溢出到磁盘上,从而使计算过程变得I/O限制(而不是CPU限制)。

进一步阅读

我强烈建议阅读整章《调整Spark》和Spark编程指南。还请查看Alexey Grishchenko关于Spark内存管理的博客文章。


非常感谢您详细的回答。我正在仔细阅读并会尽快回复您。有一个评论,我读了《深入剖析内存管理》,似乎暗示当RAM不足时,Spark将使用DISK,因此在某种程度上,执行程序可用的内存也应考虑该执行程序的磁盘空间!我仍然不确定一个人是否可以简单地决定在节点上加载任意数量的数据并对其进行操作。 - MaatDeamon
是的,没错,多余的数据会溢出到磁盘上。一般来说,我希望避免Spark在磁盘上溢出,因为这会使执行速度变慢很多。 - Nikolay Vasiliev
非常有见地,谢谢!“辅助”JVM数据结构会导致OOM随着分区记录数量增加还是随着其字节大小增加而增长?也许您心中有两种类型的例子? - bonnal-enzo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接