Вот некоторые пояснения из документации R:
parLapply , parSapply и parApply - это параллельные версии lapply,
Подать и подать заявку. Куски вычислений статически распределяются по
узлы, использующие clusterApply . По умолчанию количество чанков одинаково
как количество узлов. parLapplyLB , parSapplyLB являются балансировкой нагрузки
версии, предназначенные для использования при применении FUN к различным элементам
X занимает довольно переменное количество времени, и либо функция
детерминированные или воспроизводимые результаты не требуются. Куски
вычисления динамически распределяются между узлами с использованием clusterApplyLB .
Обратите внимание, что в R / 3.5.0 внесены некоторые изменения:
Начиная с R 3.5.0, количество чанков по умолчанию равно удвоенному числу
узлы. До версии 3.5.0 (фиксированное) количество порций было таким же, как
количество узлов. Что касается clusterApplyLB , с балансировкой нагрузки
узел, который выполняет определенную работу, является недетерминированным и
симуляции, которые назначают потоки ГСЧ узлам, не будут воспроизводиться.
clusterApply вызывает веселье на первом узле с аргументами x [[1]] и
..., на втором узле с x [[2]] и ... и т. д., переработка
узлы по мере необходимости.
Существует clauterApplyLB
, который работает немного по-другому:
clusterApplyLB является версией балансировки нагрузки clusterApply. Если
длина n из х не больше, чем число узлов р, то задание
отправлено на n узлов. В противном случае первые p заданий размещаются по порядку на
р узлов. Когда первая работа завершается, следующая работа помещается на
узел, который стал свободным; это продолжается до тех пор, пока все работы не будут завершены.
Использование clusterApplyLB может привести к лучшему использованию кластера, чем
используя clusterApply , но увеличение связи может уменьшить
спектакль. Кроме того, узел, который выполняет конкретное задание,
недетерминирована. Это означает, что симуляции, которые назначают потоки ГСЧ
к узлам не будут воспроизводиться.
Поэтому, когда вы используете parApply
, ваша матрица делится на 5 блоков. Каждый кусок обрабатывается одним из ядер. В случае семейства функций par * ApplyLB элементы назначаются ядрам одно за другим, и как только ядро завершает свою задачу, ему назначается другое.
Вот вывод следующего кода:
library(parallel)
my.mat <- matrix(c(1:20,rep(0,20)), ncol=2)
head(my.mat)
# [,1] [,2]
# [1,] 1 0
# [2,] 2 0
# [3,] 3 0
# [4,] 4 0
# [5,] 5 0
# [6,] 6 0
cl <- makeCluster(5, "FORK")
parApply(cl = cl, X = my.mat, MARGIN = 1, FUN = function(x){print(paste("sum= ", sum(x), " pid=",Sys.getpid()))})
# [1] "sum= 1 pid= 42569"
# [2] "sum= 2 pid= 42569"
# [3] "sum= 3 pid= 42569"
# [4] "sum= 4 pid= 42569"
# [5] "sum= 5 pid= 42570"
# [6] "sum= 6 pid= 42570"
# [7] "sum= 7 pid= 42570"
# [8] "sum= 8 pid= 42570"
# [9] "sum= 9 pid= 42571"
# [10] "sum= 10 pid= 42571"
# [11] "sum= 11 pid= 42571"
# [12] "sum= 12 pid= 42571"
# [13] "sum= 13 pid= 42572"
# [14] "sum= 14 pid= 42572"
# [15] "sum= 15 pid= 42572"
# [16] "sum= 16 pid= 42572"
# [17] "sum= 17 pid= 42573"
# [18] "sum= 18 pid= 42573"
# [19] "sum= 19 pid= 42573"
# [20] "sum= 20 pid= 42573"
stopCluster(cl)
Обратите внимание на разницу со следующим выводом (посмотрите, как распределяются значения pid), если я использую parLapplyLB
с размером чанка = 1:
mylist <- 1:20
cl <- makeCluster(5, "FORK")
parLapplyLB(cl = cl, X = mylist,function(x){print(paste("sum= ", sum(x), " pid=",Sys.getpid()))}, chunk.size = 1)
# [[1]]
# [1] "sum= 1 pid= 64019"
#
# [[2]]
# [1] "sum= 2 pid= 64020"
#
# [[3]]
# [1] "sum= 3 pid= 64021"
#
# [[4]]
# [1] "sum= 4 pid= 64022"
#
# [[5]]
# [1] "sum= 5 pid= 64023"
#
# [[6]]
# [1] "sum= 6 pid= 64019"
#
# [[7]]
# [1] "sum= 7 pid= 64020"
#
# [[8]]
# [1] "sum= 8 pid= 64019"
#
# [[9]]
# [1] "sum= 9 pid= 64020"
#
# [[10]]
# [1] "sum= 10 pid= 64019"
# . . .
stopCluster(cl)