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/