Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala spark-RDD的折叠方法解释_Scala_Apache Spark_Rdd - Fatal编程技术网

Scala spark-RDD的折叠方法解释

Scala spark-RDD的折叠方法解释,scala,apache-spark,rdd,Scala,Apache Spark,Rdd,我正在运行Spark-1.4.0为Hadoop-2.4(在本地模式下)预先构建的程序来计算DoubleRDD的平方和。我的Scala代码看起来像 sc.parallelize(Array(2., 3.)).fold(0.0)((p, v) => p+v*v) 它给出了一个令人惊讶的结果97.0 与Scala版本的fold Array(2., 3.).fold(0.0)((p, v) => p+v*v) 这将给出预期的答案13.0 由于缺乏理解,我很可能在代码中犯了一些棘手的错误。

我正在运行Spark-1.4.0为Hadoop-2.4(在本地模式下)预先构建的程序来计算DoubleRDD的平方和。我的Scala代码看起来像

sc.parallelize(Array(2., 3.)).fold(0.0)((p, v) => p+v*v)
它给出了一个令人惊讶的结果
97.0

与Scala版本的
fold

Array(2., 3.).fold(0.0)((p, v) => p+v*v)
这将给出预期的答案
13.0

由于缺乏理解,我很可能在代码中犯了一些棘手的错误。我已经阅读了
RDD.fold()
中使用的函数应该如何通信,否则结果可能取决于分区等。例如,如果我将分区数更改为1

sc.parallelize(Array(2., 3.), 1).fold(0.0)((p, v) => p+v*v)
代码将在我的机器上为我提供
169.0


有人能解释一下这里到底发生了什么吗?

好吧,事实上,以下几点很好地解释了这一点:

使用给定的关联和交换函数以及中性“零值”,聚合每个分区的元素,然后聚合所有分区的结果。允许函数op(t1,t2)修改t1并将其作为结果值返回,以避免对象分配;然而,它不应该修改t2

这与Scala等函数式语言中为非分布式集合实现的折叠操作有些不同。这种折叠操作可以单独应用于分区,然后将这些结果折叠成最终结果,而不是按照定义的顺序将折叠顺序应用于每个元素。对于不可交换的函数,其结果可能不同于应用于非分布式集合的折叠

为了说明正在发生的事情,让我们尝试一步一步地模拟正在发生的事情:

val rdd = sc.parallelize(Array(2., 3.))

val byPartition = rdd.mapPartitions(
    iter => Array(iter.fold(0.0)((p, v) => (p +  v * v))).toIterator).collect()
它给我们提供了类似于这个
Array[Double]=Array(0.0,0.0,0.0,4.0,0.0,0.0,0.0,9.0)

byPartition.reduce((p, v) => (p + v * v))
返回97


需要注意的重要一点是,根据分区组合的顺序,不同运行的结果可能有所不同。

谢谢!你的解释证实了我的嫌疑犯-
(2*2)*(2*2)+(3*3)*(3*3)=97
。在第二种情况下,它类似于
(2*2+3*3)*(2*2+3*3)=169
。我想这就是为什么
foldLeft
foldRight
在星火顺序中没有对应关系的原因,在“分布式”折叠中根本没有意义。实际上,在下面的例子中
Array(2,3.)
你甚至可以得到25或85,因此我最后的评论。一般来说,若函数不是可交换的和关联的,就会发生奇怪的事情。这里处理事情的正确方法是映射然后折叠:
rdd.map(x=>x*x).fold(0.0)(+)
。有趣的是,PySpark处理事情的方式似乎不同,对于(2,3.)输入O_O返回13,分区数相同。我认为PySpark也有同样的限制,请参见以下结果
sc.parallelize([2,3.].fold(0.0,lambda p,v:p+v*v)
生成
49
sc.parallelize([2,3.],100).fold(0.0,lambda p,v:p+v*v)
生成
13
是的。它只应用
op(obj,acc)
中的函数,而不是
op(acc,obj)
因此,如果分区中只有一个元素,那么它在
mapPartitions
阶段中是不平方的:)