让我们考虑使用spark这样一段python伪代码。
rdd1 = sc.textFile("...")
rdd2 = rdd1.map().groupBy().filter()
importantValue = rdd2.count()
rdd3 = rdd1.map(lambda x : x / importantValue)
在DAG
spark任务中,创建rdd1
后有两个分支。两个分支都使用rdd1
,但第二个分支(计算rdd3
)也使用来自rdd2
(importantValue
)的汇总值。我假设DAG
看起来像这样:
我对吗?如果是,我们是否可以假设计算
rdd1
中使用的rdd3
仍然在内存中处理?或者我们必须缓存rdd1
以防止重复加载?
更一般地说,如果DAG
看起来像这样:
我们可以假设两个分支都是相似地计算并使用
rdd1
的相同副本吗?或者Spark驱动程序会一个接一个地计算这些分支,因为这是两个不同的阶段?我知道在执行之前,火花驱动程序会将DAG
分成几个阶段和更详细的逻辑部分 - tasks
。一个阶段内的任务可以用pararell计算,因为内部没有洗牌阶段,但是图像中的两个pararell分支怎么样?我知道所有的直觉都在思考rdd抽象(lazy evaluetion等),但这并不会让我更容易理解。请给我任何建议。
答案 0 :(得分:1)
我认为DAG看起来像这样:我是对的吗?
是
如果是,我们可以假设计算rdd3中使用的rdd1仍在内存中处理吗?
没有。 Spark利用惰性评估来处理数据。这意味着在需要之前不会计算任何内容。除非有明确的陈述,否则不会存储任何内容。
或者我们必须缓存rdd1以防止重复加载?
确切地说,您需要缓存rdd1以防止文本文件被读取两次。
更一般地说,如果DAG看起来像这样:我们可以假设两个分支都是相似地计算并使用相同的rdd1副本吗?或者Spark驱动程序会一个接一个地计算这些分支,因为这是两个不同的阶段?
这两个分支将不会并行处理,因为它们具有单独的谱系。通常,在采取措施之前不会处理任何数据。每当需要一个结果(读取,调用一个动作)时,将发生所有进行转换的数据处理和给定沿袭中的当前动作。之后,除非调用cache
,否则内存中不会存在任何数据。
有关转换与操作的解释,请参阅此deck
答案 1 :(得分:1)
我们可以假设计算rdd3中使用的rdd1仍然在内存中处理吗?或者我们必须缓存rdd1以防止重复加载?
rdd1
未缓存。要对其进行缓存,您需要显式缓存它,并确保.cache()
返回的RDD存储在用于创建rdd2
的变量中:
rdd1 = sc.textFile("...").cache()
rdd2 = rdd1.map().groupBy().filter()
如果要将其添加到您的图表中,rdd1
和rdd2
之间会有另一个RDD。
我们可以假设两个分支都是相似地计算并使用相同的rdd1副本吗?或者Spark驱动程序会一个接一个地计算这些分支,因为这是两个不同的阶段?
什么决定了并行运行的工作是不是(分支机构)沿袭,它是工作请求本身。假设你跑了:
rdd4.count()
rdd5.count()
这将执行rdd1
- > rdd2
- > rdd4
然后计数,然后 rdd1
- > {{1} } - GT; rdd3
。这个计算将是连续的。