在Spark + Scala中序列化/广播大型地图

时间:2018-06-18 21:29:44

标签: java scala apache-spark spark-streaming distributed-computing

我的数据集由数据点组成,这些数据点是5000个元素的数组(双打),每个数据点都有一个clusterId。

出于我正在解决的问题的目的,我需要为每个clusterId聚合这些数组(逐个元素),然后在每个数据点和它各自的聚合簇数组之间进行点积计算。

我正在处理的数据点总数为4.8毫米,它们分成~50k簇。

我使用' reduceByKey'获取每个clusterId的聚合数组(这是我的关键) - 使用这个数据集,我有两个不同的选项:

  • 将聚合(clusterId,aggregateVector)对加入原始数据集 - 以便每个分区都可以使用每个aggregateVector
  • 在本地收集(clusterId,aggregateVector)的rdd并将其序列化回我的执行程序 - 再次,这样我就可以将aggregateVectors用于每个分区

我的理解是连接导致基于连接键的重新分区,所以在我的情况下,我的键的唯一值是〜50k,这将非常慢。

我尝试的是第二种方法 - 我设法收集了RDD localy - 并将其转换为clusterId的Map作为键,并将5000元素的Array [Double]作为值。

但是,当我尝试将此变量广播/序列化为Closure时,我得到了一个' java.lang.OutOfMemoryError:请求的数组大小超过VM限制& #39;&#39 ;.

我的问题是 - 鉴于我的问题的本质,我需要为每个执行者提供聚合数据,考虑到聚合数据集(在我的情况下为50k x 5000)可能是相当的,最好的方法是什么大?

由于

1 个答案:

答案 0 :(得分:0)

我强烈推荐加入。 5000个值x 50,000个元素x每个值8个字节已经是2 GB,这是可以管理的,但它确实在严重减慢了事情,并且可能会破坏一些东西"大概。

你是对的,重新分配有时可能会很慢,但我认为你更关心它而不是必要的。它仍然是完全并行/分布式操作,这使其基本上具有无限可扩展性。收集到驱动程序中的东西不是。