在SparkML Transformer中缓存数据集

时间:2018-07-19 03:57:20

标签: scala apache-spark machine-learning apache-spark-ml

我正在尝试在管道中使用 Spark ML变形金刚。此管道中的一项任务是使用 join 键将传入的数据集现有参考数据连接。

参考数据很大,但是可以在join键上进行预分区。如果我想多次使用此转换器,而只想将参考数据加载到内存一次,我可以在转换器的生命周期中缓存参考数据吗?(可以假设参考数据是在某个地方的实木复合地板文件中

1 个答案:

答案 0 :(得分:1)

首先,请确保您确实需要在Spark层进行缓存。读取Parquet的速度很快,联网的文件系统的速度很快,并且OS缓冲区高速缓存非常大。根据您的环境和工作集大小,您可能不需要在Spark层进行缓存(这样做甚至可能会损害性能)。

如果您确定一般来说缓存是有意义的,那么这个问题就比较棘手,因为即使有人将您已经缓存的内容传递给您,您也想做正确的事情(在这种情况下,您不需要缓存它,并且将来不希望对其进行缓存)。您可以先检查数据集是否已缓存,然后再进行缓存:

if (refdata.storageLevel == StorageLevel.NONE) refdata.cache()

以这种方式有条件地缓存参考数据非常适合在实际构建Transformer时进行,因为cache在访问参考数据之前不会起作用。

何时取消缓存数据是一个棘手的问题。如果某人(甚至您)已经通过了您缓存的参考数据,那么您就不会缓存它(并且您以后也不想取消缓存,以免给他们带来惊喜)。如果您跟踪是否在Transformer中缓存了参考数据(例如,在名为uncached的值中),那么您应该有一个必要时进行清理的方法,并在您使用时显式调用完成了。

将它们放在一起,您的变形金刚看起来像这样:

class ExampleModel(private val uncached: Boolean, private val refdata: Broadcast[DataFrame]) extends Model[Example] {

  def this(df: Broadcast[DataFrame]) {
    this(df.value.storageLevel == StorageLevel.NONE, df)
  }

  if(uncached) refdata.value.cache();

  // ...

  def cleanup { if (uncached) { refdata.value.uncache() } ; refdata.destroy() }

}