Когда мне нужно использовать sfExport (пакет R Snowfall)
Я использую снегопад для параллельных вычислений. Я всегда на одной машине с несколькими процессорами (>20 ядер). Я обрабатываю большое количество данных (>20 ГБ). sfExport() занимает очень много времени.
Когда я запускаю свои тестовые коды на своем ноутбуке и проверяю загрузку процессора, иногда он также работает без sfExport().
Некоторые части моего кода являются вложенными функциями sfLapply(). Подобно:
func2 <- function(c,d, ...) {
result <-
list(x = c+d,
y = ..,
...
)
return(result)
}
func1 <- function(x, a, b, c, ...) {
library(snowfall)
d <- a+b
result <- sfLapply(as.list(b$row), func2, c, d, ...)
return(result)
}
result <- sfLapply(as.list(data.table$row), func1, a, b, c, ..)
Когда мне действительно нужно экспортировать данные во все процессоры?
спасибо и наилучшие пожелания Нико
1 ответ
Если вы экспортируете объект объемом 20 ГБ всем работникам кластера, это займет много времени и много памяти. Каждый работник получит свою собственную копию этого объекта объемом 20 ГБ, поэтому вам может потребоваться уменьшить количество работников, чтобы уменьшить общее использование памяти, в противном случае ваша машина может начать работать с перебоями, и ваша программа может в конечном итоге умереть. В этом случае использование меньшего количества рабочих может работать намного быстрее. Конечно, если ваша машина имеет 512 ГБ ОЗУ, использование 20 рабочих может быть оправдано, хотя отправка этого объекта всем рабочим займет много времени.
Если каждому работнику нужен определенный фрейм данных или матрица для выполнения рабочей функции, то экспорт, вероятно, является правильным решением. Если каждому работнику нужна только часть объекта, вы должны разделить его и отправить только ту часть, которая нужна каждому из работников. Ключ заключается в том, чтобы точно определить, какие данные нужны рабочей функции, и отправлять только то, что нужно.
Если кажется, что объект волшебным образом отображается на рабочих, даже если вы его не экспортируете, возможно, вы захватываете этот объект в закрытии функции. Вот пример:
library (snowfall)
sfInit (parallel=TRUE , cpus=4)
fun <- function() {
x <- 100
worker <- function(n) x * n
sfLapply(1:1000, worker)
}
r <- fun()
Это прекрасно работает, но не очевидно, как переменная "x" отправляется работникам кластера. Ответ в том, что "x" сериализуется вместе с функцией "работник", когда sfLapply отправляет задачи работникам, потому что "работник" определен внутри функции "веселье". В этом случае экспортировать "x" рабочим через sfExport - пустая трата времени. Также обратите внимание, что хотя этот метод хорошо работает с sfLapply, он не очень хорошо работает с такими функциями, как sfClusterApply и sfClusterApplyLB, которые не выполняют чанкинг задач, как sfLapply, хотя это только проблема, если "x" очень большой.
Я не буду вдаваться в подробности этого вопроса, кроме как скажу, что вы должны быть очень осторожны, когда ваша рабочая функция определена внутри другой функции.