Разница между параллельной картой и параллельным циклом for - PullRequest
5 голосов
/ 16 апреля 2019

Когда я прочитал документ Джулии о многоядерных параллельных вычислениях, я заметил, что есть и параллельная карта pmap, и цикл for @distributed for.

Из документации "Джулия pmap - эторазработан для случая, когда каждый вызов функции выполняет большой объем работы. Напротив, @distributed for может обрабатывать ситуации, когда каждая итерация крошечная ".

В чем разница между pmap и @distributed for?Почему @distributed for медлителен для большого объема работы?

Спасибо

Ответы [ 2 ]

5 голосов
/ 16 апреля 2019

Проблема в том, что pmap выполняет балансировку нагрузки, в то время как @distributed for разделяет задания на равные части.Вы можете подтвердить это, запустив эти два примера кода:

julia> @time res = pmap(x -> (sleep(x/10); println(x)), [10;ones(Int, 19)]);
      From worker 2:    1
      From worker 3:    1
      From worker 4:    1
      From worker 2:    1
      From worker 3:    1
      From worker 4:    1
      From worker 3:    1
      From worker 2:    1
      From worker 4:    1
      From worker 4:    1
      From worker 2:    1
      From worker 3:    1
      From worker 2:    1
      From worker 3:    1
      From worker 4:    1
      From worker 4:    1
      From worker 3:    1
      From worker 2:    1
      From worker 4:    1
      From worker 5:    10
  1.106504 seconds (173.34 k allocations: 8.711 MiB, 0.66% gc time)

julia> @time @sync @distributed for x in [10;ones(Int, 19)]
       sleep(x/10); println(x)
       end
      From worker 4:    1
      From worker 3:    1
      From worker 5:    1
      From worker 4:    1
      From worker 5:    1
      From worker 3:    1
      From worker 5:    1
      From worker 3:    1
      From worker 4:    1
      From worker 3:    1
      From worker 4:    1
      From worker 5:    1
      From worker 4:    1
      From worker 5:    1
      From worker 3:    1
      From worker 2:    10
      From worker 2:    1
      From worker 2:    1
      From worker 2:    1
      From worker 2:    1
  1.543574 seconds (184.19 k allocations: 9.013 MiB)
Task (done) @0x0000000005c5c8b0

И вы увидите, что большое задание (значение 10) заставляет pmap выполнять все небольшие задания на работниках, отличных от того, который был полученбольшая работа (в моем примере работник 5 выполнял только работу 10, в то время как работники 2 до 4 выполняли все другие работы).С другой стороны, @distributed for назначил одинаковое количество заданий каждому работнику.Таким образом, работник, который получил работу 10 (работник 2 во втором примере), все еще должен был выполнить четыре коротких работы (поскольку каждый работник в среднем должен выполнять 5 рабочих мест - в моем примере всего 20 рабочих мести 4 работников).

Теперь преимущество @distributed for состоит в том, что если работа недорогая, то равное распределение работ между работниками позволяет избежать необходимости динамического планирования, которое также не является бесплатным.

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

3 голосов
/ 16 апреля 2019

pmap имеет аргумент batch_size, который по умолчанию равен 1. Это означает, что каждый элемент коллекции будет отправлен один за другим доступным рабочим или задачам, которые должны быть преобразованыФункция, которую вы предоставили.Если каждый вызов функции выполняет большой объем работы и, возможно, каждый вызов отличается по времени, которое требуется, использование pmap имеет преимущество, заключающееся в том, что рабочие не отпускаются, а другие работают, потому что, когда работник завершает одно преобразование, он будетпопросить следующий элемент для преобразования.Следовательно, pmap эффективно балансирует нагрузку между работниками / задачами.

@distributed for-loop, однако, разбивает заданный диапазон среди работников один раз в начале, не зная, сколько времени займет каждый раздел диапазона.Рассмотрим, например, коллекцию матриц, где первые сто элементов коллекции - это матрицы 2 на 2, следующие сто элементов - матрицы 1000 на 1000, и мы хотели бы взять инверсию каждой матрицы, используя @distributed for-loop и 2 рабочих процесса.

@sync @distributed for i = 1:200
    B[i] = inv(A[i])
end

Первый работник получит все матрицы 2 на 2, а второй получит матрицы 1000 на 1000.Первый работник выполнит все преобразования очень быстро и бездействует, в то время как другой продолжит выполнять работу очень долго.Несмотря на то, что вы используете 2 рабочих, основная часть всей работы будет эффективно выполняться в последовательном для второго рабочего, и вы почти не получите выгоды от использования более одного рабочего.Эта проблема известна как балансировка нагрузки в контексте параллельных вычислений.Проблема может также возникнуть, например, когда один процессор работает медленно, а другой работает быстро, даже если работа, которую нужно выполнить, является однородной.

Однако для очень небольших преобразований работы используется pmap с небольшимРазмер пакета создает издержки связи, которые могут быть значительными, так как после каждого пакета процессору необходимо получить следующий пакет от вызывающего процесса, тогда как при @distributed for-loop каждый рабочий процесс в начале будет знать, какая часть диапазонаон отвечает за.

Выбор между pmap и @distributed for-loop зависит от того, чего вы хотите достичь.Если вы собираетесь преобразовать коллекцию, как в map, и каждое преобразование требует большого объема работы, и эта сумма варьируется, то вам, вероятно, будет лучше выбрать pmap.Если каждое преобразование очень маленькое, то вам, вероятно, будет лучше выбрать @distributed for-loop.

Обратите внимание, что если вам нужна операция сокращения после преобразования, @distributed for-loop уже обеспечиваетВо-первых, большинство сокращений будет применяться локально, а окончательное сокращение будет происходить в процессе вызова.Однако с pmap вам придется самостоятельно справляться с сокращением.

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

https://docs.julialang.org/en/v1/manual/parallel-computing/

...