Scala 如何在Spark中的每个分区上求和
我创建了一个类,并使用该类创建RDD。我想计算每个分区上类成员的LoudnessRate之和。该总和将在以后用于计算每个分区的平均响度率。 我尝试了下面的代码,但它不计算Sum并返回0.0。 我的代码是 物体斯巴克巴特{ def mainargs:数组[字符串]:单位={ val numPartitions=3 val N=50 val d=5 val MinVal=-10 val MaxVal=10 val conf=new SparkConf.setMasterlocallylocal.setAppNamespark Sum val sc=新的SparkContextconf val ba=List.fillNnew BATd、MinVal、MaxVal val rdd=sc.parallelizeba,numPartitions var arrSum=Array.fillnumPartitions0.0//声明将为每个分区保存和的数组 rdd.mapPartitionsWithIndexk,迭代器=>iterator.mapx=>arrSumk+=x.LoudnessRate.collect 每一个println的arrSum } } 类BAT dim:Int,min:Double,max:Double扩展了可序列化的{ val random=新随机 变量位置:List[Double]=List.filldim random.nextDouble*max-min+min 变量速度:List[Double]=List.filldim math.random 脉冲电压:双=0.1 var响度率:双=0.95 var频率:Double=math.random 变量适应度:Double=math.random 变量BestPosition:List[Double]=List.FillDiMath.random var BestFitness:Double=math.random }Scala 如何在Spark中的每个分区上求和,scala,apache-spark,rdd,partitioning,Scala,Apache Spark,Rdd,Partitioning,我创建了一个类,并使用该类创建RDD。我想计算每个分区上类成员的LoudnessRate之和。该总和将在以后用于计算每个分区的平均响度率。 我尝试了下面的代码,但它不计算Sum并返回0.0。 我的代码是 物体斯巴克巴特{ def mainargs:数组[字符串]:单位={ val numPartitions=3 val N=50 val d=5 val MinVal=-10 val MaxVal=10 val conf=new SparkConf.setMasterlocallylocal.se
问题是,您使用的是一个在驱动程序中声明并在执行器中更新的常规集合。无论何时,您都需要使用蓄能器
应该有助于将我的评论更改为要求的答案。原始评论 您正在executor JVM中修改arrSum,并在dirver JVM中打印其值。您可以将迭代器映射到单例迭代器,并使用collect将值移动到驱动程序。另外,不要使用iterator.map产生副作用,iterator.foreach就是为了产生副作用 下面是一个示例代码片段,它是如何实现的。首先创建一个带有两个分区的RDD,0->1,2,3和1->4,5。当然,您在实际代码中不需要这一点,但由于sc.parallelize行为随环境而变化,这将始终创建统一的RDD来重现:
object DemoPartitioner extends Partitioner {
override def numPartitions: Int = 2
override def getPartition(key: Any): Int = key match {
case num: Int => num
}
}
val rdd = sc
.parallelize(Seq((0, 1), (0, 2), (0, 3), (1, 4), (1, 5)))
.partitionBy(DemoPartitioner)
.map(_._2)
然后是实际的技巧:
val sumsByPartition = rdd.mapPartitionsWithIndex {
case (partitionNum, it) => Iterator.single(partitionNum -> it.sum)
}.collect().toMap
println(sumsByPartition)
产出:
Map(0 -> 6, 1 -> 9)
您正在executor JVM中修改arrSum,并在dirver JVM中打印其值。您可以将迭代器映射到单例迭代器,并使用collect将值移动到驱动程序。另外,不要将iterator.map用于副作用,iterator.foreach用于that@ollik1如果你添加了代码,这应该是一个答案。@ollik1你能添加代码吗?@AlexeyRomanov和yari,很公平,添加了代码作为答案。这会根据我的需要提供所需的结果。还有一个问题,这是计算总和的最佳方法,还是我们可以做更多的优化?关于速度,我想说,在大多数情况下,它几乎是计算每个分区的和的最快方法,而它本身并不是使用Spark的常见操作。执行者之间并没有混乱,这通常是缓慢的部分,只有最低限度的数据通过网络发送到驱动程序以收集。