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中的每个分区上求和_Scala_Apache Spark_Rdd_Partitioning - Fatal编程技术网

Scala 如何在Spark中的每个分区上求和

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

我创建了一个类,并使用该类创建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 }
问题是,您使用的是一个在驱动程序中声明并在执行器中更新的常规集合。无论何时,您都需要使用蓄能器


应该有助于将我的评论更改为要求的答案。原始评论

您正在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的常见操作。执行者之间并没有混乱,这通常是缓慢的部分,只有最低限度的数据通过网络发送到驱动程序以收集。