Насколько полезен Parallel Seq для выполнения последовательности операторов? - PullRequest
5 голосов
/ 24 мая 2019

У меня есть небольшая программа, использующая List.par

val x = List(1,2,3,4,5).par.map(y => {
    Thread.sleep(2000)
    println(y)
    y + 1
})

println(x)

Выход:

3
1
4
5
2
ParVector(2, 3, 4, 5, 6)

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

Моя цель - выполнить последовательность операторов вставки в базу данных SQL параллельно.

В настоящее время я использую для понимания . Я хочу использовать ParSeq , так как количество операторов увеличивается.

Но я боюсь, приведет ли это к снижению производительности. (Если в реализации имеется дополнительный код * map для сохранения порядка, это приводит к снижению производительности).

Пожалуйста, предложите мне, как это сделать.

1 Ответ

6 голосов
/ 24 мая 2019

Документация (раздел «Семантика») объясняет, что есть только два возможных сценария, которые могут привести к неправильному поведению:

  1. Побочные действия могут привести к недетерминизму
  2. Неассоциативные операции приводят к недетерминизму

Первое, что вы заметили сами с println утверждениями. Второй легко проверяется с помощью неассоциативной двоичной операции, такой как вычитание:

val list = (1 to 100).toList
val a = list.par.reduce(_ - _)

println(a) 

Попробуйте выполнить приведенный выше фрагмент кода пару раз.

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

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

1 - (2 - (3 - 4))

или

((1 - 2) - 3) - 4

Именно поэтому параллельная обработка коллекции обычно поддерживает reduce и fold, но не foldLeft и foldRight.

...