使用火花的笛卡尔积
Posted
技术标签:
【中文标题】使用火花的笛卡尔积【英文标题】:Cartesian product using spark 【发布时间】:2017-07-27 11:28:51 【问题描述】:我有两个序列 A 和 B。我们想生成一个布尔序列,其中 A 中的每个元素都有一个出现在 B 中的子序列。例如:
a = ["abababab", "ccffccff", "123123", "56575656"]
b = ["ab", "55", "adfadf", "123", "5656"]
output = [True, False, True, True]
A 和 B 不适合内存。一种解决方案可能如下:
val a = sc.parallelize(List("abababab", "ccffccff", "123123", "56575656"))
val b = sc.parallelize(List("ab", "55", "adfadf", "123", "5656"))
a.cartesian(b)
.map(case (x,y) => (x, x contains y) )
.reduceByKey(_ || _).map(w => w._1 + "," + w._2).saveAsTextFile("./output.txt")
可以理解,不需要计算笛卡尔积,因为一旦我们找到满足条件的前几个序列,我们就可以停止搜索。以A
的第一个元素为例。如果我们从头开始迭代B
,B
的第一个元素是一个子序列,因此输出是True
。在这种情况下,我们非常幸运,但一般情况下不需要验证所有组合。
问题是:有没有其他方法可以优化这个计算?
【问题讨论】:
【参考方案1】:我相信简短的回答是“不”:)
我也不认为将 Spark 与 迭代 的功能进行比较是不公平的。您必须记住,Spark 适用于无法选择顺序处理的大型数据集。它与可能在许多不同机器上同时执行的数千个任务并行运行您的功能。它这样做是为了确保处理将在合理的时间内完成,即使A
的第一个元素与B
的非常 last 元素匹配。
相比之下,迭代或循环是同时比较两个元素的顺序操作。它非常适合小型数据集,但不适用于大型数据集,绝对不适合分布式处理。
【讨论】:
但我想知道是否有其他方法可以通过使用一种短路来执行此计算。最后,计算为f(a_1, b_1) || f(a_1, b_2) || ... || f(a_1, b_n)
。想象一下,您需要执行昂贵的操作,而不是查找子序列。当您已经知道答案是真的时,您真的希望进行所有这些昂贵的操作吗?
但问题是,f(a_1, b_1)
的计算可以在 machineX 上的 taskA 中进行,而 f(a_1, b_2)
在 machineY 上的 taskB 中同时计算等等。 f(a_1, b_2)
可能很好地评估为 true,但这在所有计算完成并且数据在 reduceByKey
中四处移动之后才全局知道。以上是关于使用火花的笛卡尔积的主要内容,如果未能解决你的问题,请参考以下文章