缓存和检查点是否应该在 DataSet 上一起使用?如果是这样,它是如何工作的?

Should cache and checkpoint be used together on DataSets? If so, how does this work under the hood?

我正在研究 Spark ML 管道,我们在较大的数据集上遇到 OOM 错误。在训练之前我们使用 cache();我将其换成 checkpoint(),我们的内存需求显着下降。但是,在 RDDcheckpoint() 的文档中它说:

It is strongly recommended that this RDD is persisted in memory, otherwise saving it on a file will require recomputation.

DataSet 的检查点没有给出相同的指导,这正是我正在使用的。无论如何按照上面的建议,我发现内存需求实际上比单独使用 cache() 略有增加。

我的期望是当我们这样做时

...
ds.cache()
ds.checkpoint()
...

对检查点的调用强制评估 DataSet,它在被检查点之前同时缓存。之后,对 ds 的任何引用都将引用缓存的分区,如果需要更多内存并且分区被疏散,则将使用检查点分区而不是重新评估它们。这是真的吗,还是在幕后发生了一些不同的事情?理想情况下,我希望尽可能将 DataSet 保留在内存中,但从内存的角度来看,使用缓存和检查点方法似乎没有任何好处。

TL;DR你不会在后续的操作中受益于in-memory缓存(),但你仍然应该考虑缓存,如果计算ds 很贵。

说明

您的期望

ds.cache()
ds.checkpoint()
...

the call to checkpoint forces evaluation of the DataSet

是正确的。 Dataset.checkpoint 有不同的风格,允许急切和惰性检查点,the default variant is eager

def checkpoint(): Dataset[T] = checkpoint(eager = true, reliableCheckpoint = true)

因此后续 操作应重用检查点文件。

然而,在幕后的 Spark 只是 applies checkpoint on the internal RDD,所以评估规则没有改变。 Spark 首先评估 action,然后创建 checkpoint(这就是为什么首先推荐缓存)。

因此,如果您省略 ds.cache()ds 将在 ds.checkpoint() 中计算两次:

因此没有任何变化,仍然推荐使用 cache,尽管与普通 RDD 相比,推荐可能会稍微弱一些,因为 Dataset 缓存被认为是计算昂贵的,并且取决于上下文,简单地重新加载数据可能更便宜(请注意 Dataset.count 没有 cache 通常是优化的,而 Dataset.countcache 不是 - ) .