scala параллельные коллекции не согласованы

#scala #parallel-processing

#scala #параллельная обработка

Вопрос:

Я получаю противоречивые ответы из следующего кода, который я нахожу странным.

 import scala.math.pow

val p = 2
val a = Array(1,2,3)

println(a.par
    .aggregate("0")((x, y) => s"$y pow $p; ", (x, y) => x   y))

for (i <- 1 to 100) {
  println(a.par
    .aggregate(0.0)((x, y) => pow(y, p), (x, y) => x   y) == 14)
}

a.map(x => pow(x,p)).sum
  

В коде a.par ... вычисляется 14 или 10 . Может ли кто-нибудь объяснить, почему он вычисляет непоследовательно?

Ответ №1:

В вашей функции «seqop», которая является первой функцией, к которой вы переходите aggregate , вы определяете логику, которая используется для объединения элементов в одном разделе. Ваша функция выглядит следующим образом:

 (x, y) => pow(y, p)
  

Проблема в том, что вы не накапливаете результаты раздела. Вместо этого вы выбрасываете свой аккумулятор x . Каждый раз, когда вы получаете 10 в результате, вычисление 2^2 отбрасывалось.

Если вы измените свою функцию, чтобы учитывать накопленное значение, вы будете получать 14 каждый раз:

 (x, y) => x   pow(y, p)
  

Ответ №2:

Правильный способ использования aggregate

     a.par.aggregate(0.0)(
        (acc, value) => acc   pow(value, 2), (acc1, acc2) => acc1   acc2
    )
  

Используя (x, y) => pow(y,2) , вы не накапливали элемент в накопителе, а просто заменяли накопитель на pow(y,2) .