下面的代码计算两个用户之间的距离度量,由案例类指定:
case class User(name: String, features: Vector[Double])
val ul = for (a <- 1 to 100) yield (User("a", Vector(1, 2, 4)))
var count = 0;
def distance(userA: User, userB: User) = {
val subElements = (userA.features zip userB.features) map {
m => (m._1 - m._2) * (m._1 - m._2)
}
val summed = subElements.sum
val sqRoot = Math.sqrt(summed)
count += 1;
println("count is " + count)
((userA.name, userB.name), sqRoot)
}
val distances = ul.par.map(m => ul.map(m2 => {
(distance(m, m2))
})).toList.flatten
val sortedDistances = distances.groupBy(_._1._1).map(m => (m._1, m._2.sortBy(s => s._2)))
println(sortedDistances.get("a").get.size);
这执行比较100个用户的笛卡尔积:10000比较。我计算每次比较,代表bu var count
计数值通常小于10000,但迭代的项数总是10000.这是因为par产生多个线程,其中一些将在执行println语句之前完成。但是,所有这些都将在par代码块内完成 - 在评估distances.groupBy(_._1._1).map(m => (m._1, m._2.sortBy(s => s._2)))
之前。
答案 0 :(得分:0)
在你的例子中,你有一个单独的非同步变量,你正在从多个线程变异,就像你说的那样。这意味着每个线程在任何时候都可能具有count
的陈旧副本,因此当它们递增时,它们将压缩已发生的任何其他写入,从而导致计数小于它应该的数量。
您可以使用synchronized
函数
...
val subElements = (userA.features zip userB.features) map {
m => (m._1 - m._2) * (m._1 - m._2)
}
val summed = subElements.sum
val sqRoot = Math.sqrt(summed)
this.synchronized {
count += 1;
}
println("count is " + count)
((userA.name, userB.name), sqRoot)
...
使用'this.synchronized'将使用包含对象作为锁定对象。有关Scala同步的更多信息,建议您阅读Twitter's Scala School.