为什么Spark并行化randomSplit

时间:2017-02-05 07:54:49

标签: apache-spark

我有一些Spark代码可以创建一系列RDD。在最后,我调用randomSplit将其拆分为3组,然后将每个写入磁盘。所以第一阶段是:

  1. 获取一些数据
  2. 做一些转换
  3. 缓存结果
  4. 通过randomSplit
  5. 拆分
  6. 将所有拆分写入磁盘
  7. 因为步骤(4)将事物分成3组,所以这里有3个不同的Spark阶段。在第一阶段结束时,我们开始用完第一阶段任务,但有执行程序可用:

    enter image description here

    此时已经计算了几个分区的数据集。据我所知,randomSplit以分区为基础运行;换句话说,它不需要shuffle或collect - 它只是在每个分区的基础上随机选择行。如果这是正确的,那么第2阶段的某些任务就没有理由无法在可用的执行程序上运行 - 它们的RDD的分区已被计算和缓存。为什么Spark不启动某些阶段2任务以利用可用资源。

    注意:显然“他们可以,但他们没有”在这里回答是完全有效的。我想我真正要问的是,是否存在一些我没有想到的技术原因使得这不可能(或非常困难)或者这只是实施中的疏忽?

    这是代码的简化版本(在Kotlin中):

    fun run(sc: JavaSparkContext, opts: Options) {
        val allData = fetchABunchOfData()
    
        val allDataRdd = sc.parallelize(allData)
    
        val taggedAndTokenized = allDataRdd.mapPartitions { addTagsAndTokens(it) }
    
        // Convert each ResponseData to a JSON String
        val jsonStrings = taggedAndTokenized.map {
            val mapper = AnxJsonUtils.getMapper()
            mapper.writeValueAsString(it)
        }
    
        // the randomSplit below creates 3 distinct RDD lineags so if we don't cache the parsing stuff we'll parse the
        // entire document set twice.
        jsonStrings.cache()
        val trainValidTest =
                jsonStrings.randomSplit(doubleArrayOf(opts.trainFrac, opts.validFrac, opts.testFrac), splitSeed)
        trainValidTest[0].saveAsTextFile(opts.outPath + "/" + TRAIN_NAME)
        trainValidTest[1].saveAsTextFile(opts.outPath + "/" + VALID_NAME)
        trainValidTest[2].saveAsTextFile(opts.outPath + "/" + TEST_NAME)
    }
    

1 个答案:

答案 0 :(得分:1)

由于多种原因,saveAsTextFile是阻止通话。这意味着Spark master将在第一个保存指令完成之前不会收到第二个保存指令。

那就是说,如果你想利用这些可用资源,你可以做的就是在三个不同的线程中调用saveAsTextFile并等待他们的未来。一旦工人在第一个任务上完成了分区,它就可以在第二个任务上开始。