Spark:执行程序内存超过物理限制

use*_*641 4 apache-spark spark-dataframe

我的输入数据集大约是 150G。我正在设置

--conf spark.cores.max=100 
--conf spark.executor.instances=20 
--conf spark.executor.memory=8G 
--conf spark.executor.cores=5 
--conf spark.driver.memory=4G
Run Code Online (Sandbox Code Playgroud)

但由于数据在执行者之间分布不均匀,我一直在得到

Container killed by YARN for exceeding memory limits. 9.0 GB of 9 GB physical memory used
Run Code Online (Sandbox Code Playgroud)

这是我的问题:

1. Did I not set up enough memory in the first place? I think 20 * 8G > 150G, but it's hard to make perfect distribution, so some executors will suffer
2. I think about repartition the input dataFrame, so how can I determine how many partition to set? the higher the better, or?
3. The error says "9 GB physical memory used", but i only set 8G to executor memory, where does the extra 1G come from?
Run Code Online (Sandbox Code Playgroud)

谢谢!

Rya*_*ier 5

使用纱线时,还有另一个设置可以计算为执行程序发出纱线容器请求的大小:

spark.yarn.executor.memoryOverhead
Run Code Online (Sandbox Code Playgroud)

它默认为 0.1 * 您的执行程序内存设置。它定义了除了您指定的执行程序内存之外还需要多少额外的开销内存。先尝试增加这个数字。

此外,纱线容器不会为您提供任意大小的内存。它只会返回分配的内存大小是其最小分配大小的倍数的容器,该大小由以下设置控制:

yarn.scheduler.minimum-allocation-mb
Run Code Online (Sandbox Code Playgroud)

将其设置为较小的数字将降低您“超出”您要求的金额的风险。

我通常还将下面的键设置为大于我想要的容器大小的值,以确保火花请求控制我的执行器有多大,而不是在它们上踩线。这是纱线将发出的最大容器尺寸。

nodemanager.resource.memory-mb
Run Code Online (Sandbox Code Playgroud)


Fok*_*ong 5

9GB 由您作为参数添加的 8GB 执行器内存组成,spark.yarn.executor.memoryOverhead设置为.1,因此容器的总内存spark.yarn.executor.memoryOverhead + (spark.yarn.executor.memoryOverhead * spark.yarn.executor.memoryOverhead)8GB + (.1 * 8GB) \xe2\x89\x88 9GB

\n\n

您可以使用单个执行器运行整个过程,但这需要很长时间。要理解这一点,您需要了解分区和任务的概念。分区的数量由您的输入和操作定义。例如,如果您从 hdfs 读取 150gb csv,并且您的 hdfs 块大小为 128mb,那么您最终将得到150 * 1024 / 128 = 1200分区,它直接映射到 Spark UI 中的 1200 个任务。

\n\n

每一个任务都将由执行者接手。您不需要将所有 150GB 都保存在内存中。例如,当你只有一个执行器时,你显然不会从 Spark 的并行功能中受益,但它只会从第一个任务开始,处理数据,并将其保存回 dfs,然后开始处理下一个任务。

\n\n

您应该检查什么:

\n\n
    \n
  • 输入分区有多大?输入文件是否可以分割?如果单个执行器必须加载大量内存,那么它肯定会耗尽内存。
  • \n
  • 你正在执行什么样的操作?例如,如果您执行基数非常低的联接,则最终会得到大量分区,因为具有特定值的所有行最终都位于相同的分区中。
  • \n
  • 执行的操作非常昂贵或效率低下?任何笛卡尔积等
  • \n
\n\n

希望这可以帮助。快乐火花!

\n

  • 我想你想说的是 executor-memory + (spark.yarn.executor.memoryOverhead * executor-memory) 这是 8GB + (.1 * 8GB) ≈ 9GB (2认同)