簡體   English   中英

為什么我的火花工作有這么多的任務? 默認情況下獲取200個任務

[英]Why so many tasks in my spark job? Getting 200 Tasks By Default

我有一個spark作業,它接收來自hdfs的8條記錄的文件,做一個簡單的聚合並將其保存回hdfs。 當我這樣做時,我注意到有數百個任務。

我也不確定為什么有這么多工作? 我覺得工作更像是一個動作發生的時候。 我可以推測為什么 - 但我的理解是,在這段代碼中它應該是一個工作,它應該分解為階段,而不是多個工作。 為什么不把它分解成各個階段,為什么它會闖入工作崗位?

至於200多個任務,由於數據量和節點數量微乎其微,當只有一個聚合和幾個過濾器時,每行數據有25個任務是沒有意義的。 為什么每個原子操作每個分區只有一個任務?

這是相關的scala代碼 -

import org.apache.spark.sql._
import org.apache.spark.sql.types._
import org.apache.spark.SparkContext._
import org.apache.spark.SparkConf

object TestProj {object TestProj {
  def main(args: Array[String]) {

    /* set the application name in the SparkConf object */
    val appConf = new SparkConf().setAppName("Test Proj")

    /* env settings that I don't need to set in REPL*/
    val sc = new SparkContext(appConf)
    val sqlContext = new SQLContext(sc)
    import sqlContext.implicits._

    val rdd1 = sc.textFile("hdfs://node002:8020/flat_files/miscellaneous/ex.txt")

     /*the below rdd will have schema defined in Record class*/
     val rddCase =  sc.textFile("hdfs://node002:8020/flat_files/miscellaneous/ex.txt")
      .map(x=>x.split(" "))    //file record into array of strings based spaces
      .map(x=>Record(
        x(0).toInt,
        x(1).asInstanceOf[String],
        x(2).asInstanceOf[String],
        x(3).toInt))


    /* the below dataframe groups on first letter of first name and counts it*/
    val aggDF = rddCase.toDF()
      .groupBy($"firstName".substr(1,1).alias("firstLetter"))
      .count
      .orderBy($"firstLetter")

    /* save to hdfs*/ 
 aggDF.write.format("parquet").mode("append").save("/raw/miscellaneous/ex_out_agg")

  }

    case class Record(id: Int
      , firstName: String
      , lastName: String
      , quantity:Int)

}

下面是單擊應用程序后的屏幕截圖 在此輸入圖像描述

以下是查看id 0的特定“作業”時顯示的階段 在此輸入圖像描述

下面是單擊具有200多個任務的舞台時屏幕的第一部分

在此輸入圖像描述

這是舞台內屏幕的第二部分 在此輸入圖像描述

下面是點擊“執行者”選項卡后 在此輸入圖像描述

根據要求,這里是工作ID 1的階段

在此輸入圖像描述

以下是具有200個任務的作業ID 1中的階段的詳細信息

在此輸入圖像描述

這是一個經典的Spark問題。

用於讀取的兩個任務(第二個圖中的階段Id 0)是defaultMinPartitions設置,它設置為2.您可以通過讀取REPL sc.defaultMinPartitions的值來獲取此參數。 它也應該在“環境”選項卡下的Spark UI中可見。

你可以看一下GitHub中的代碼 ,看看這到底發生了什么。 如果您希望在讀取時使用更多分區,只需將其添加為參數,例如sc.textFile("a.txt", 20)

現在有趣的部分來自第二階段出現的200個分區(第二個階段的階段Id 1)。 好吧,每次有一個shuffle,Spark需要決定shuffle RDD有多少個分區。 可以想象,默認值為200。

您可以使用以下方法更改:

sqlContext.setConf("spark.sql.shuffle.partitions", "4”)

如果使用此配置運行代碼,您將看到200個分區不再存在。 如何設置此參數是一種藝術。 也許選擇2倍的核心數量(或其他)。

我認為Spark 2.0有一種方法可以自動推斷shuffle RDD的最佳分區數。 期待那樣!

最后,您獲得的作業數量與生成的優化Dataframe代碼產生的RDD操作數量有關。 如果您閱讀Spark規范,它會說每個RDD操作都會觸發一個作業。 當您的操作涉及Dataframe或SparkSQL時,Catalyst優化器將找出執行計划並生成一些基於RDD的代碼來執行它。 在你的情況下,很難確切地說它為什么會使用兩個動作。 您可能需要查看優化的查詢計划,以確切了解正在執行的操作。

我有個類似的問題。 但在我的場景中,我並行化的集合比Spark計划的任務數量少(導致火花有時奇怪地表現)。 使用強制分區號我能解決這個問題。

它是這樣的:

collection = range(10) # In the real scenario it was a complex collection
sc.parallelize(collection).map(lambda e: e + 1) # also a more complex operation in the real scenario

然后,我在Spark日志中看到:

INFO YarnClusterScheduler: Adding task set 0.0 with 512 tasks

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM