是否可以在Spark中的每个分区上重置长累加器?

时间:2019-08-05 19:56:50

标签: scala apache-spark worker

我正在尝试在每个分区上重置longAccumulator,但是无法重置。我正在尝试这种方式。

val list = (1 to 100).toList
val rdd = sc.parallelize(list,4)
val acc = sc.longAccumulator("1L")

rdd.mapPartitionsWithIndex{(i,iterator) => 
acc.reset()
acc.add(iterator.sum)
iterator
}

当前,此代码不会重置每个分区上的累加器。在驱动程序中,我们可以通过调用reset()方法将累加器重置为零。我想问问是否可以为每个分区重置累加器。

我有n个分区。我想将值的总和存储在List中的每个分区上。对于分区0,其总和应存储在列表的索引0中,依此类推。

2 个答案:

答案 0 :(得分:1)

在大多数情况下,哪个分区(或它们的总和)中的值无关紧要并易于更改。但是,仍然可以进行计算。


您不想使用累加器对每个分区的值求和。相反,您可以模拟计算总和并将其作为新的RDD返回。

要按分区顺序获取总和列表,请返回具有总和的索引并对其进行排序。然后将其删除。

rdd.mapPartitionsWithIndex{(i,iterator) => 
  Seq((i, iterator.reduce(_ + _))).toIterator
}.collect().sortBy(_._1).map(_._2)

这将为您提供一个按顺序排列总和的数组。

答案 1 :(得分:1)

根据您的最终游戏,您可能要使用自定义地图累加器。 看一下this。如下使用它:

val myAcc = new ByKeyAdditiveAccumulator[Int, Long]
sparkContext.register(myAcc)
...
rdd.foreachPartition(partition => 
   acc.add((TaskContext.get.partitionId(), partition.size))
...
import scala.collection.JavaConverters._
val partitionCount = myAcc.value.asScala