"spark.yarn.executor.memoryOverhead"和"spark.memory.offHeap.size"的区别是什么?

8

我在Yarn上运行Spark。我不理解以下设置之间的区别:spark.yarn.executor.memoryOverheadspark.memory.offHeap.size。两者都似乎是为Spark执行器分配堆外内存的设置。应该使用哪一个?另外,对于执行器堆外内存的推荐设置是什么?

非常感谢!

2个回答

19

TL;DR: 对于Spark 1.x和2.x,总的堆外内存 = spark.executor.memoryOverhead(其中包括spark.offHeap.size) 对于Spark 3.x,总的堆外内存 = spark.executor.memoryOverhead + spark.offHeap.size(来源于此页面

详细解释:

spark.executor.memoryOverhead由资源管理器(如YARN)使用,而spark.memory.offHeap.size由Spark核心(内存管理器)使用。这种关系在不同版本中略有不同。

Spark 2.4.5及之前版本:

spark.executor.memoryOverhead应该包括spark.memory.offHeap.size。这意味着,如果您指定了offHeap.size,则需要将此部分手动添加到memoryOverhead以供YARN使用。如下面代码所示,从YarnAllocator.scala,当YARN请求资源时,它不知道任何有关offHeap.size的信息:

private[yarn] val resource = Resource.newInstance(
    executorMemory + memoryOverhead + pysparkWorkerMemory,
    executorCores)

然而,在 Spark 3.0 中行为发生了改变:

spark.executor.memoryOverhead 不再包括 spark.memory.offHeap.size。在请求资源时,YARN 将为您包含 offHeap.size。根据新的文档

注意:附加内存包括 PySpark 执行程序内存(当未配置 spark.executor.pyspark.memory 时)和由同一容器中运行的其他非执行程序进程使用的内存。运行执行程序的容器的最大内存大小由 spark.executor.memoryOverhead、spark.executor.memory、spark.memory.offHeap.size 和 spark.executor.pyspark.memory 的总和确定。

代码中也可以看出:

private[yarn] val resource: Resource = {
    val resource = Resource.newInstance(
      executorMemory + executorOffHeapMemory + memoryOverhead + pysparkWorkerMemory, executorCores)
    ResourceRequestHelper.setResourceRequests(executorResourceRequests, resource)
    logDebug(s"Created resource capability: $resource")
    resource
  }

了解更多有关此更改的详细信息,请参阅此Pull Request

至于您的第二个问题,执行器 offheap 内存的推荐设置取决于您的应用程序,并且您需要进行一些测试。我发现这个页面对进一步解释非常有帮助:

Off-heap 内存是减少 GC 暂停的好方法,因为它不在 GC 的范围内。然而,它带来了序列化和反序列化的开销。后者又使得 off-heap 数据有时会被放到堆内存中,从而暴露给 GC。此外,Project Tungsten 带来的新数据格式(字节数组)有助于降低 GC 开销。这两个原因使得 Apache Spark 应用程序中使用 off-heap 内存应该经过认真规划,并进行测试。

顺便提一下,spark.yarn.executor.memoryOverhead 已经弃用,更改为 spark.executor.memoryOverhead,这适用于 YARN 和 Kubernetes。


你能否详细说明一下这两个参数之间的区别? - Venkatesan Muniappan

0
  1. spark.yarn.executor.memoryOverhead用于静态内存管理器。这在旧版Spark(如1.2)中使用。

为每个执行器分配的堆外存储器量(以兆字节为单位)。这是用于计算虚拟机开销、interned字符串、其他本地开销等的内存。这往往随着执行器大小增长而增长(通常为6-10%)。

您可以在较旧的Spark文档中找到此信息,例如Spark1.2文档:

https://spark.apache.org/docs/1.2.0/running-on-yarn.html

  • spark.memory.offHeap.size在UnifiedMemoryManager中使用,默认情况下自1.6版本后使用。
  • 可以用于非堆分配的内存绝对量(以字节为单位)。这个设置不会影响堆内存使用,因此如果您的执行者的总内存消耗必须符合某些硬限制,那么请确保相应地缩小JVM堆大小。当 spark.memory.offHeap.enabled=true 时,必须将其设置为正值。

    您可以在最新的Spark文档中找到此信息,例如Spark2.4文档:

    https://spark.apache.org/docs/2.4.4/configuration.html
    

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