EMR 忽略 spark 提交参数 (memory/cores/etc)

EMR ignores spark submit parameters (memory/cores/etc)

我正在尝试使用我的 EMR 集群上的所有资源。

集群本身是 4 台 m4.4xlarge 机器(1 个驱动程序和 3 个工作程序),具有 16 个 vCore、64 GiB 内存、EBS Storage:128 GiB

通过 cli 启动集群时,我看到了以下选项(所有 3 个选项都在同一个数据管道中执行):

只需使用“maximizeResourceAllocation”,不使用任何其他 spark-submit 参数

这里只给出了 2 个执行器

不要放任何东西,让 spark-defaults 完成它们的工作

给出以下低质量执行者

使用 AWS 指南了解如何在 EMR 中配置集群

根据 this guide,我推导出以下 spark-submit 个参数:

      "--conf",
      "spark.executor.cores=5",
      "--conf",
      "spark.executor.memory=18g",
      "--conf",
      "spark.executor.memoryOverhead=3g",
      "--conf",
      "spark.executor.instances=9",

      "--conf",
      "spark.driver.cores=5",
      "--conf",
      "spark.driver.memory=18g",

      "--conf",
      "spark.default.parallelism=45",

      "--conf",
      "spark.sql.shuffle.partitions=45",

Aaand 仍然没有运气:

现在我做了 look everywhere 我可以在互联网上找到,但找不到任何关于为什么 EMR 不使用所提供的所有资源的解释。也许我遗漏了一些东西,或者这可能是预期的行为,但是当“maximizeAllocation”仅跨越具有 3 个工作人员的集群上的 2 个执行程序时,那里出现了问题。

更新:

所以今天 运行 一个 不同的数据管道 我使用“maximizeResourceAllocation”得到了这个: 这比其他的要好得多,但在使用的内存和执行器方面仍然有很多不足(尽管 EMR 团队的人说 emr 将执行器合并为超级执行器以提高性能)。

您是否尝试过设置 --master yarn 参数并将参数 spark.executor.memoryOverhead 替换为 spark.yarn.executor.memoryOverhead

我想添加我的答案,尽管我无法解释您看到的所有情况。

但我会尽力解释那些我能解释的。

案例 1:最大资源分配

这是 Amazon EMR 特定的配置,我不完全确定 Amazon EMR 在此配置中做了什么。

When you enable maximizeResourceAllocation, EMR calculates the maximum compute and memory resources available for an executor on an instance in the core instance group. It then sets the corresponding spark-defaults settings based on the calculated maximum values

以上文字片段来自here

看起来集群可能有一些配置,EMR 会为此计算资源分配。不过我不是很确定。

我想知道的一个后续问题是,您是否正在 运行集群上安装其他应用程序?这可以改变 EMR 为确定资源分配所做的计算。

案例 2:默认值

我可以解释一下。

这是在 Spark 中使用了一个叫做 DynamicResourceAllocation 的东西。来自 spark website:

Spark provides a mechanism to dynamically adjust the resources your application occupies based on the workload. This means that your application may give resources back to the cluster if they are no longer used and request them again later when there is demand. This feature is particularly useful if multiple applications share resources in your Spark cluster.

查看 link above,它提到 Amazon EMR 使用动态资源分配作为 Spark 的默认设置。

因此,您看到的执行程序大小和数量是由于您 运行 的工作量所致。

案例 3:特定值

要理解这里的分配,需要了解Spark的内存分配模型

Spark 执行程序和驱动程序 运行 作为 JVM。他们将 JVM 的内存划分为

  1. On-Heap Space,进一步分为
    • 存储内存 - 用于缓存数据
    • Execution Memory - 暂存数据用于shuffle,join sort
    • User Memory - 用于 RDD 转换和依赖图
    • 预留内存 - 用于 spark 内部对象
  2. 堆外Space - 通常默认禁用

堆上space的内存分配如下:

X = Executor Memory Configured
X' = X - 300MB (for reserved memory - taken to start of with to let spark work)

User Memory = X' * 0.40 = User Memory
Storage + Execution Memory = X' * 0.60

The Storage and execution memory is split 50-50.

以你为例

X  = 18 GB ~ 18000 MB
X' = 18000 - 300 MB = 17700 MB = Remaining

User = 17700 * 0.40 = 7080
Storage + Execution = 17700 * 0.60 = 10620 ~ 10 GB
And that is what you're seeing in your Storage Memory column and On-heap storage memory column.

Note2: the boundary between Storage and Execution space is flexible. If required, storage could evict all of execution and vice-versa.

插入数字,它似乎与您的观察结果一致。这就解释了为什么你分配的原始 18G 中只得到 10G。

希望至少让您看到的两个案例更加清晰。