我有一些Spark代码可以创建一系列RDD。在最后,我调用randomSplit
将其拆分为3组,然后将每个写入磁盘。所以第一阶段是:
randomSplit
因为步骤(4)将事物分成3组,所以这里有3个不同的Spark阶段。在第一阶段结束时,我们开始用完第一阶段任务,但有执行程序可用:
此时已经计算了几个分区的数据集。据我所知,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)
}
答案 0 :(得分:1)
由于多种原因,saveAsTextFile
是阻止通话。这意味着Spark master将在第一个保存指令完成之前不会收到第二个保存指令。
那就是说,如果你想利用这些可用资源,你可以做的就是在三个不同的线程中调用saveAsTextFile
并等待他们的未来。一旦工人在第一个任务上完成了分区,它就可以在第二个任务上开始。