Spark Scala:如何使用rdd的每个3个元素?

时间:2016-02-18 06:02:24

标签: scala apache-spark

大家。

我有这样的问题:

我有非常大的rdd:数十亿元素,如:

Array[((Int, Int), Double)] = Array(((0,0),729.0), ((0,1),169.0), ((0,2),1.0), ((0,3),5.0), ...... ((34,45),34.0), .....)

我需要做这样的操作:

按键(i,j)获取每个元素的值,并将

添加到其中
min(rdd_value[(i-1, j)],rdd_value[(i, j-1)], rdd_value[(i-1, j-1)])

如何在不使用collect()之后执行此操作collect()我已经Java memory errror因为我的rdd非常大。

非常感谢!

我尝试从python中实现这个算法。当时间序列是rdds。

def DTWDistance(s1, s2):
    DTW={}

    for i in range(len(s1)):
        DTW[(i, -1)] = float('inf')
    for i in range(len(s2)):
        DTW[(-1, i)] = float('inf')
    DTW[(-1, -1)] = 0

    for i in range(len(s1)):
        for j in range(len(s2)):
            dist= (s1[i]-s2[j])**2
            DTW[(i, j)] = dist + min(DTW[(i-1, j)],DTW[(i, j-1)], DTW[(i-1, j-1)])

    return sqrt(DTW[len(s1)-1, len(s2)-1])

现在我应该用for循环执行最后一次操作。 dist已经计算好了。

示例:

输入(如矩阵):

4 5 1
7 2 3
9 0 1

Rdd看起来像

rdd.take(10)

Array(((1,1), 4), ((1,2), 5), ((1,3), 1), ((2,1), 7), ((2,2), 2), ((2,3), 3), ((3,1), 9), ((3,2), 0), ((3,3), 1))

我想做这个操作

rdd_value[(i, j)] = rdd_value[(i, j)] + min(rdd_value[(i-1, j)],rdd_value[(i, j-1)], rdd_value[(i-1, j-1)])

例如:

((1, 1), 4) = 4 + min(infinity, infinity, 0) = 4 + 0 = 4


4 5 1
7 2 3
9 0 1

然后

((1, 2), 5) = 5 + min(infinity, 4, infinity) = 5 + 4 = 9


4 9 1
7 2 3
9 0 1

然后

...

然后

((2, 2), 2) = 2 + min(7, 9, 4) = 2 + 4 = 6


4 9 1
7 6 3
9 0 1

然后 .....

((3, 3), 1) = 1 + min(3, 0, 2) = 1 + 0 = 1

1 个答案:

答案 0 :(得分:2)

简短的回答是,您尝试解决的问题无法使用Spark进行有效和简洁的表达。如果您选择普通RDD是分布式矩阵,那么这并不重要。

要理解为什么你必须考虑Spark编程模型。基本的Spark概念是依赖关系图,其中每个RDD依赖于一个或多个父RDD。如果您的问题定义如下:

  • 给出初始矩阵 M 0
  • 代表 i< - 1..n
    • 找到矩阵 M i 其中 M i (m,n) = M i - 1 (m,n) + min(M i - 1 (m-1,n ),M i - 1 (m-1,n-1),M i - 1 (m中,n-1)

然后使用Spark API(伪代码)来表达是微不足道的:

rdd
    .flatMap(lambda ((i, j), v): 
        [((i + 1, j), v), ((i, j + 1), v), ((i + 1, j + 1), v)])
    .reduceByKey(min)
    .union(rdd)
    .reduceByKey(add)

不幸的是,您试图表达同一数据结构中各个值之间的依赖关系。除了它之外,还有一个难以并行化的问题,更不用说分发了。

这种类型的动态编程很难并行化,因为在不同的点上完全或几乎完全是顺序的。当您尝试计算例如 M i (0,0) M i (m,n) 没有什么可以并行化。它很难分发,因为它可以在块之间生成复杂的依赖关系。

通过计算单个块并表示这些块之间的依赖关系或使用迭代算法并通过显式图(GraphX)传播消息,可以通过非常简单的方法在Spark中处理此问题,但这很难做到。

在一天结束时,有一些工具可以比Spark更适合这种类型的计算。