我正在尝试更多地使用scalas不可变集合,因为这很容易并行化,但我遇到了一些新手问题。我正在寻找一种从操作中(有效地)创建新的Vector的方法。准确地说,我想要的东西如下
val v : Vector[Double] = RandomVector(10000)
val w : Vector[Double] = RandomVector(10000)
val r = v + w我测试了以下内容:
// 1)
val r : Vector[Double] = (v.zip(w)).map{ t:(Double,Double) => t._1 + t._2 }
// 2)
val vb = new VectorBuilder[Double]()
var i=0
while(i<v.length){
vb += v(i) + w(i)
i = i + 1
}
val r = vb.result}
与使用Array相比,这两种方法都需要很长时间:
[Vector Zip/Map ] Elapsed time 0.409 msecs
[Vector While Loop] Elapsed time 0.374 msecs
[Array While Loop ] Elapsed time 0.056 msecs
// with warm-up (10000) and avg. over 10000 runs有没有更好的方法呢?我认为使用zip/map/reduce的优势在于,只要集合支持这一点,它就可以并行运行。
谢谢
发布于 2011-06-01 22:06:54
Vector不是专门针对Double的,所以使用它会带来相当大的性能损失。如果您正在执行一个简单的操作,那么在单个核心上使用一个数组可能比在整台机器上使用Vector或其他通用集合要好(除非您有12+核心)。如果您仍然需要并行化,还可以使用其他机制,例如使用scala.actors.Futures.future创建实例,每个实例在范围的一部分上执行工作:
val a = Array(1,2,3,4,5,6,7,8)
(0 to 4).map(_ * (a.length/4)).sliding(2).map(i => scala.actors.Futures.future {
var s = 0
var j = i(0)
while (j < i(1)) {
s += a(j)
j += 1
}
s
}).map(_()).sum // _() applies the future--blocks until it's done当然,您需要在一个更长的数组(以及具有四个内核的机器上)上使用它来进行并行化,以提高性能。
发布于 2011-06-01 20:36:39
当您使用多个高阶方法时,您应该使用延迟构建的集合:
v1.view zip v2 map { case (a,b) => a+b }如果不使用视图或迭代器,每个方法都将创建一个新的不可变集合,即使不需要它们也是如此。
不可变的代码可能不会像可变的代码那样快,但惰性集合将大大改善代码的执行时间。
发布于 2011-06-01 22:53:30
数组不是类型擦除的,向量是类型擦除的。基本上,在处理无法克服的原语时,JVM为Array提供了优于其他集合的优势。Scala的specialization可能会降低这一优势,但考虑到它们在代码大小方面的成本,它们不可能在所有地方都使用。
https://stackoverflow.com/questions/6200005
复制相似问题