如何在Spark中成对合并分区?

时间:2015-08-27 13:40:09

标签: apache-spark

我有一组点(每个点都是文本文件中的一行),我在Spark的分区之间传播。

我使用mapPartitions操作,这导致我在每个分区中的一半点(并不重要,为什么以及如何)。

现在,我希望按对合并分区,因此分区#1和#2将是合并分区,分区#3和#4将是第二个合并分区,因此只有一个。

我将继续运行mapPartitions,直到我只剩下几个分区。 我怎么能用Spark做到这一点?

这里的Hadoop模拟是我按对合并输出文件并再次运行tak。

我将再次尝试澄清它:在运行mapPartitions后,我有x个分区, 我想成对合并它们,所以我会有x / 2分区并再次运行mapPartitions等等。

2 个答案:

答案 0 :(得分:2)

使用treeAggregate作为这样的模型应该可以解决这个问题:

from math import log

def binaryReduce(rdd, f):
    assert log(rdd.getNumPartitions(), 2) % 1 == 0
    def mapPartition(i, iter):
        i = i / 2
        for x in iter:
            yield i, x

    while rdd.getNumPartitions() != 1:
        rdd = (rdd
            .mapPartitionsWithIndex(mapPartition)
            .reduceByKey(f, rdd.getNumPartitions() / 2)
            .values())

    return rdd.first()

如果您更喜欢更明确的方法,请始终保持分区编号:

def binaryReduce(rdd, f):
    assert log(rdd.getNumPartitions(), 2) % 1 == 0

    def initPartition(i, iter):
        for x in iter:
            yield i, x

    rdd = rdd.mapPartitionsWithIndex(initPartition)

    while rdd.getNumPartitions() != 1:
        rdd = (rdd
            .reduceByKey(f)
            .map(lambda x: (x[0] / 2, x[1]))
            .partitionBy(rdd.getNumPartitions() / 2))

    return rdd.values().reduce(f)

对于Python 3.0+,请务必将/替换为//

答案 1 :(得分:1)

这个问题非常模糊。 如果我做对了,你可以在将数据映射到(键,值)之后尝试使用reduceByKey。

http://spark.apache.org/docs/latest/programming-guide.html#parallelized-collections

希望这有帮助。

编辑:你应该使用mapPartitionsWithIndex(func)和func必须是类型(Int,Iterator)=>迭代器。