我已经创建了一个类,并使用该类来创建RDD。我想在每个分区计算 LoudnessRate 的总和(类的成员)。此总和随后将用于计算每个分区的均值 LoudnessRate 。 我尝试了以下代码,但它不计算总和,并返回 0.0 。 我的代码是
object sparkBAT {
def main(args: Array[String]): Unit = {
val numPartitions = 3
val N = 50
val d = 5
val MinVal = -10
val MaxVal = 10
val conf = new SparkConf().setMaster(locally("local")).setAppName("spark Sum")
val sc = new SparkContext(conf)
val ba = List.fill(N)(new BAT(d, MinVal, MaxVal))
val rdd = sc.parallelize(ba, numPartitions)
var arrSum =Array.fill(numPartitions)(0.0) // Declare Array that will hold sum for each Partition
rdd.mapPartitionsWithIndex((k,iterator) => iterator.map(x => arrSum(k) += x.LoudnessRate)).collect()
arrSum foreach println
}
}
class BAT (dim:Int, min:Double, max:Double) extends Serializable {
val random = new Random()
var position : List[Double] = List.fill(dim) (random.nextDouble() * (max-min)+min )
var velocity :List[Double] = List.fill(dim)( math.random)
var PulseRate : Double = 0.1
var LoudnessRate :Double = 0.95
var frequency :Double = math.random
var fitness :Double = math.random
var BestPosition :List[Double] = List.fill(dim)(math.random)
var BestFitness :Double = math.random
}
答案 0 :(得分:4)
根据要求将我的评论更改为答案。原始评论
您正在修改执行程序JVM中的arrSum,并在驱动程序JVM中打印其值。您可以将迭代器映射到单例迭代器,并使用collect将值移动到驱动程序。另外,请勿将iterator.map用作副作用,而iterator.foreach是为此目的而设计的。
这是一个示例代码片段。首先使用两个分区0 -> 1,2,3
和1 -> 4,5
创建一个RDD。当然,您在实际代码中将不需要此,但是随着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)
答案 1 :(得分:0)
问题是您使用的是arrSum(常规集合),它在驱动程序中声明并在执行程序中更新。每当您这样做时,都需要使用累加器。
This应该有所帮助