Добавление неизменных векторов - PullRequest
3 голосов
/ 01 июня 2011

Я пытаюсь больше работать с неизменяемой коллекцией скал, поскольку ее легко распараллелить, но я борюсь с некоторыми проблемами новичка.Я ищу способ (эффективно) создать новый вектор из операции.Если быть точным, я хочу что-то вроде

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

}

Оба требуют очень много времени по сравнению с работой с массивом:

[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 / lower имеет то преимущество, что она может работать параллельно, как только коллекции получат такую ​​поддержку.

Спасибо

Ответы [ 3 ]

5 голосов
/ 01 июня 2011

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

Конечно, вам понадобитсяиспользовать это на гораздо более длинном массиве (и на машине с четырьмя ядрами) для распараллеливания, чтобы улучшить ситуацию.

4 голосов
/ 01 июня 2011

Массивы не стираются по типу, Векторы есть.По сути, JVM дает Array преимущество перед другими коллекциями при обработке примитивов, которые невозможно преодолеть.specialization от Scala может уменьшить это преимущество, но, учитывая стоимость кода, их нельзя использовать повсеместно.

4 голосов
/ 01 июня 2011

Вы должны использовать лениво построенные коллекции, когда вы используете более одного метода более высокого порядка:

v1.view zip v2 map { case (a,b) => a+b }

Если вы не используете представление или итератор, каждый метод создаст новую неизменяемую коллекцию, даже когдаони не нужны.

Возможно, неизменяемый код не будет таким же быстрым, как изменяемый, но отложенная коллекция значительно улучшит время выполнения вашего кода.

...