Apache spark pyspark折叠法输出
我对Apache spark pyspark折叠法输出,apache-spark,pyspark,Apache Spark,Pyspark,我对fold的输出感到惊讶,我无法想象它在做什么 我希望something.fold(0,lambda,b:a+1)将返回something中的元素数,因为fold从0开始,并为每个元素添加1 sc.parallelize([1,25,8,4,2]).fold(0,lambda a,b:a+1 ) 8 我来自Scala,fold的工作方式与我描述的一样。那么,折叠在pyspark中应该如何工作呢?谢谢你的想法 为了理解这里发生了什么,让我们看看Spark的折叠操作的定义。因为您使用的是PySp
fold
的输出感到惊讶,我无法想象它在做什么
我希望something.fold(0,lambda,b:a+1)
将返回something
中的元素数,因为fold从0开始,并为每个元素添加1
sc.parallelize([1,25,8,4,2]).fold(0,lambda a,b:a+1 )
8
我来自Scala,fold的工作方式与我描述的一样。那么,折叠在pyspark中应该如何工作呢?谢谢你的想法 为了理解这里发生了什么,让我们看看Spark的折叠操作的定义。因为您使用的是PySpark,所以我将展示代码的Python版本,但是Scala版本展示了完全相同的行为(您也可以):
(有关比较,请参阅)
Spark的折叠操作是先折叠每个分区,然后折叠结果。问题是一个空分区被折叠到零元素,因此最终的驱动程序端折叠结果是每个分区折叠一个值,而不是每个非空分区折叠一个值。这意味着折叠的结果对分区的数量敏感:
>>> sc.parallelize([1,25,8,4,2], 100).fold(0,lambda a,b:a+1 )
100
>>> sc.parallelize([1,25,8,4,2], 50).fold(0,lambda a,b:a+1 )
50
>>> sc.parallelize([1,25,8,4,2], 1).fold(0,lambda a,b:a+1 )
1
在最后一种情况下,发生的是单个分区被向下折叠到正确的值,然后该值与驱动程序处的零值一起折叠,得到1
似乎Spark的fold()
操作实际上要求fold函数除了关联函数外还具有可交换性。实际上,Spark中还有其他地方强加了这一要求,例如,在一个无序分区中,元素的顺序在不同的运行中可能是不确定的(请参阅)
我打开了一张Spark JIRA票来调查这个问题:。让我试着给出一些简单的例子来解释Spark的折叠方法。我将在这里使用pyspark
rdd1=sc.parallelize(列表([]),1)
上面这一行将创建一个带有一个分区的空rdd
rdd1.折叠(10,λx,y:x+y)
这使产量达到20%
rdd2=sc.parallelize(列表([1,2,3,4,5]),2)
上面这一行将创建值为1到5的rdd,总共有2个分区
rdd2.折叠(10,λx,y:x+y)
这将产生45%的输出
为了简单起见,在上面的例子中,这里发生的是,第0个元素是10。因此,RDD中所有数字的和现在加上10(即第0个元素+所有其他元素=>10+1+2+3+4+5=25)。现在我们还有两个分区(即分区数*第零个元素=>2*10=20)
fold发射的最终输出为25+20=45
使用类似的过程,可以清楚地了解为什么rdd1上的折叠操作会产生20作为输出
当我们有空列表时,Reduce失败,比如rdd1.Reduce(lambda x,y:x+y)
ValueError:无法减少()空RDD
如果我们认为rdd中可以有空列表,则可以使用Fold
rdd1.折叠(0,λx,y:x+y)
正如预期的那样,这将产生0的输出
感谢彻底的回答,我忽略了分区如何影响折叠。因此,为了澄清Scala的情况,RDD分区与Scala的典型折叠行为产生了重要的差异。也就是说,List(1,2,3,4).fold(0)((a,b)=>a+1)
将与Spark的sc.parallelize(List(1,2,3,4)).fold(0)((a,b)=>a+1)
@keegan,是的,没错:分区行为,加上排序不确定性的某些来源,这意味着当您使用非交换运算符时,Spark折叠的行为当前将不会像您预期的那样。为了进一步说明这一点,请尝试以下操作:在Scala中,Seq(2.0,3.0)。fold(1.0)((a,b)=>pow(b,a))
将始终返回9.0。在Spark中尝试同样的方法:sc.parallelize(Seq(2.0,3.0),2)。折叠(1.0)((a,b)=>pow(b,a))
。在我的多核笔记本电脑上,Spark版本将不确定地返回8.0或9.0,这取决于哪个分区首先完成。
>>> sc.parallelize([1,25,8,4,2], 100).fold(0,lambda a,b:a+1 )
100
>>> sc.parallelize([1,25,8,4,2], 50).fold(0,lambda a,b:a+1 )
50
>>> sc.parallelize([1,25,8,4,2], 1).fold(0,lambda a,b:a+1 )
1