【问题标题】:How to carry-over the calculated value within the RDD ? -Apache spark如何结转 RDD 中的计算值? -阿帕奇火花
【发布时间】:2015-03-23 20:01:21
【问题描述】:

已解决:这个问题没有好的解决方案

我确信这只是一个与语法相关的问题,而且答案很简单。


我想要实现的是:

-将变量传递给RDD

-根据RDD数据改变变量

-获取调整后的变量


假设我有:

变量 b = 2

val x = sc.parallelize(0 到 3)

我要做的是获得值 2+0 + 2+0+1 + 2+0+1+2 + 2+0+1+2+3 = 18 也就是说,通过执行类似的操作获得 18 的值

b = x.map(i=> ... b+i...).collect

问题是,对于每一个 i,我都需要将值 b 结转,并随着下一个 i 递增

我想使用此逻辑将元素添加到 RDD 外部的数组中

如果不先收集,我该怎么做?

【问题讨论】:

  • 这根本不是一个简单的语法相关问题。你试图做的事情是不可能的。它违背了 RDD 和分布式计算的整个概念。我建议您更具体地描述您要解决的问题,并让我们提供一个符合实际概念的解决方案。您还可以查看RDD.aggregate,这与您尝试做的类似,但适用于分布式世界。
  • 聚合是可以的,除了我需要传递一个参数(即问题中的变量“b”)而不是必要的两个。我希望你是对的,这不仅仅是一个语法问题,而且它不能用 Spark 完成。我要做的是:1.将集合传递给RDD 2.将RDD中的元素添加到集合3.检索集合注意:我不介意结果集合是否按顺序排列,我总是可以排序最后按索引。我只是不想先收集,然后从中生成一个集合。
  • 是的,你不能那样做。 RDD 是分布式的。它在其他机器上。你不能只传递一个可变集合,在里面放一些东西然后把它取回来。但是,这听起来与过滤器非常相似。为什么不过滤 RDD 然后收集结果呢?您可以在此时将它们附加到您的收藏中。
  • 谢谢!我会好好记录的!!!

标签: syntax apache-spark


【解决方案1】:

如 cmets 中所述,不可能使用 RDD 的内容来改变一个变量,因为 RDD 可能分布在许多不同的节点上,而可变变量是每个执行程序 (JVM) 的本地变量。

虽然性能不是特别好,但可以通过将顺序算法转换为可在分布式环境中执行的一系列转换来在 Spark 上实现这些要求。

使用与问题相同的示例,Spark 中的该算法可以表示为:

val initialOffset = 2
val rdd = sc.parallelize(0 to 3)
val halfCartesian = rdd.cartesian(rdd).filter{case (x,y) => x>=y}
val partialSums = halfCartesian.reduceByKey(_ + _) 
val adjustedPartials = partialSums.map{case (k,v) => v+initialOffset}
val total = adjustedPartials.reduce(_ + _)

scala> total
res33: Int = 18

请注意,cartesian 是一种非常昂贵的转换,因为它会创建 (m x n) 个元素,或者在本例中为 n^2。
这只是说这并非不可能,但可能并不理想。

如果要按顺序处理的数据量适合一台机器的内存(可能在过滤/减少之后),那么 Scala 有一个内置的收集操作来准确地实现所要求的内容:scan[Left|Right]

val arr = Array(0,1,2,3)
val cummulativeScan = arr.scanLeft(initialOffset)(_ + _)
// we remove head b/c scan adds the given element at the start of the sequence 
val result = cummulativeScan.tail.sum

result: Int = 18

【讨论】:

    猜你喜欢
    • 2014-10-09
    • 2014-12-17
    • 2019-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多