如何為Spark應用程序分配--num-executors,--execuor-cores和--executor-memory


 

轉載於:https://www.cnblogs.com/lestatzhang/p/10611321.html

 

前言

在我們提交spark程序時,應該如何為Spark集群配置–num-executors, - executor-memory和–execuor-cores 呢?

一些資源參數設置的基本知識
  • Hadoop / Yarn / OS Deamons
    當我們使用像Yarn這樣的集群管理器運行spark應用程序時,會有幾個守護進程在后台運行,如NameNode,Secondary NameNode,DataNode,JobTracker和TaskTracker等。因此,在指定num-executors時,我們需要確保為這些守護進程留下足夠的核心(至少每個節點約1 CPU核)以便順利運行。
  • Yarn ApplicationMaster(AM)
    ApplicationMaster負責協調來自ResourceManager的資源,並與NodeManagers一起執行container並監控其資源消耗。如果我們在YARN上運行Spark,那么我們需要預估運行AM所需要的資源(至少1024MB和1 CPU核)。
  • HDFS吞吐量
    HDFS客戶端遇到大量並發線程會出現一些bug。一般來說,每個executors最多可以實現5個任務的完全寫入吞吐量,因此最好將每個executors的核心數保持在該數量之下。
  • MemoryOverhead
    JVM還需要一些off heap的內存,請參考下圖中描繪的Spark和YARN中內存屬性的層次結構,

 

test

簡單來說,有以下兩個公式:

每個executor從YARN請求的內存 = spark-executor-memory + spark.yarn.executor.memoryOverhead
 
         spark.yarn.executor.memoryOverhead = Max(384MB, 7% of spark.executor-memory) 
        

 

例如當我設置 --executor-memory=20時, 我們實際請求了

20GB + memoryOverhead = 20 + 7% of 20GB = ~23GB

運行具有executors大內存的通常會導致過多的GC延遲。
運行較小的executors(例如,1G & 1 CPU core)則會浪費 單個JVM中運行多個任務所帶來的優點。

不同配置的優劣分析

現在,假設我們的集群配置如下

10 Nodes
16 cores per Node
64GB RAM per Node

 
第一種方法:使用較小的executors

`--num-executors` = `在這種方法中,我們將為每個核心分配一個executor`                  

                  = `集群的總核心數`                  

                  = `每個節點的核心數 * 集群的總節點數`                  

                  =  16 x 10 = 160                 
`--executor-cores`  = 1 (`每個executor分配的核心數目`)
`--executor-memory` = `每個executor分配的內存數`                    

                    = `每個節點內存總數數/每個節點上分配的executor數`                    

                    = 64GB/16 = 4GB

 

分析
由於每個executor只分配了一個核,我們將無法利用在同一個JVM中運行多個任務的優點。 此外,共享/緩存變量(如廣播變量和累加器)將在節點的每個核心中復制16次。 最嚴重的就是,我們沒有為Hadoop / Yarn守護程序進程留下足夠的內存開銷,我們還忘記了將ApplicationManagers運行所需要的開銷加入計算。

第二種方法:使用較大的executors

 

`--num-executors` = `在這種方法中,我們將為每個節點分配一個executor`
                  = `集群的總節點數`
                  = 10
                    
`--executor-cores` = `每個節點一個executor意味着該節點的所有核心都分配給一個執executor`
                   = `每個節點的總核心數`
                   = 16
                     
`--executor-memory` = `每個executor分配的內存數`
                    = `每個節點內存總數數/每個節點上分配的executor數`
                    = 64GB/1 = 64GB

 

分析:
每個executor都有16個核心,由於HDFS客戶端遇到大量並發線程會出現一些bug,即HDFS吞吐量會受到影響。同時過大的內存分配也會導致過多的GC延遲。

 

 

第三種方法:使用優化的executors
  • 基於上面提到的建議,讓我們為每個執行器分配5個核心, 即--executor-cores = 5
  • 為每個節點留出1個核心用於Hadoop / Yarn守護進程, 即每個節點可用的核心數 = 16-1 = 15。 因此,群集中核心的可用總數= 15 x 10 = 150
  • –num-executors =(群集中核心的可用總數/每個executors分配的核心數)= 150/5 = 30
  • 為ApplicationManager留下預留1個executors的資源, 即--num-executors = 29
  • 每個節點的executors數目 = 30/10 = 3
  • 群集中每個節點的可使用的總內存數 64GB - 1GB = 63GB
  • 每個executor的內存= 64GB / 3 = 21GB
  • 預留的 off heap overhead = 21GB * 7% ~ 1.47G
  • 所以,實際的--executor-memory = 21 - 1.47G ~ 19GB

參考資料
how-to-tune-your-apache-spark-jobs-part-2

distribution_of_executors_cores_and_memory_for_spark_application

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM