Используя parLapply параллельного интерфейса: невозможно получить доступ к переменным в параллельном коде
Недавно у меня был компьютер с несколькими ядрами, и я учусь использовать параллельные вычисления. Я довольно опытный с lapply
и было сказано parLapply
работает очень похоже. Я не работаю правильно, хотя. Кажется, я должен явно поместить все в parLapply
заставить его работать (то есть используемые функции, переменные и т. д.). С lapply
он читает из родительской среды и parLapply
похоже, не делает этого. Так что в моем примере ниже я мог бы заставить все работать, поместив всю информацию внутри parLapply
но если я использую это внутри определенной пользователем функции, я не могу явно поставить text.var
Внутри parLapply
,
library(parallel)
text.var <- rep("I like cake and ice cream so much!", 20)
ntv <- length(text.var)
gc.rate <- 10
pos <- function(i) {
paste(sapply(strsplit(tolower(i), " "), nchar), collapse=" | ")
}
lapply(seq_len(ntv), function(i) {
x <- pos(text.var[i])
if (i%%gc.rate==0) gc()
return(x)
}
)
#doesn't work
cl <- makeCluster(mc <- getOption("cl.cores", 4))
parLapply(cl, seq_len(ntv), function(i) {
x <- pos(text.var[i])
if (i%%gc.rate==0) gc()
return(x)
}
)
#does work but have to specify all the stuff inside parLapply
cl <- makeCluster(mc <- getOption("cl.cores", 4))
parLapply(cl, seq_len(ntv), function(i) {
######stuff I have to put inside parLapply##########
text.var <- rep("I like cake and ice cream so much!", 20)
ntv <- length(text.var)
gc.rate <- 10
pos <- function(i) {
paste(sapply(strsplit(tolower(i), " "), nchar), collapse=" | ")
}
######stuff I have to put inside parLapply##########
x <- pos(text.var[i])
if (i%%gc.rate==0) gc()
return(x)
}
)
Как я могу пройти text.var
, ntv
, gc.rate
, а также pos
в parLapply
без явного помещения их внутрь? (Я предполагаю, что вы передаете их как список как-то)
PS Windows 7 машина, поэтому мне нужно использовать parLapply
Я думаю
3 ответа
Вам необходимо экспортировать эти переменные в другие процессы R в кластере:
cl <- makeCluster(mc <- getOption("cl.cores", 4))
clusterExport(cl=cl, varlist=c("text.var", "ntv", "gc.rate", "pos"))
Альтернативный метод, предоставленный Мартином Морганом, также будет работать здесь.
Этот метод предоставляет объекты каждому узлу кластера непосредственно в parLapply
вызов без необходимости использовать экспорт кластера:
library(parallel)
text.var <- rep("I like cake and ice cream so much!", 20)
ntv <- length(text.var)
gc.rate <- 10
pos <- function(i) {
paste(sapply(strsplit(tolower(i), " "), nchar), collapse=" | ")
}
cl <- makeCluster(mc <- getOption("cl.cores", 4))
parLapply(cl, seq_len(ntv), function(i, pos, text.var, ntv, gc.rate) {
x <- pos(text.var[i])
if (i%%gc.rate==0) gc()
return(x)
}, pos, text.var, ntv, gc.rate
)
out1<-lapply(seq_len(ntv), function(i) {x <- pos(text.var[i]);if (i%%gc.rate==0) gc();return(x)})
out2<-parLapply(cl, seq_len(ntv), function(i) {x <- pos(text.var[i]);if (i%%gc.rate==0) gc();return(x)})
> identical(out1,out2)
# [1] TRUE
require(rbenchmark)
benchmark(lapply(seq_len(ntv), function(i) {x <- pos(text.var[i]);if (i%%gc.rate==0) gc();return(x)}),parLapply(cl, seq_len(ntv), function(i) {x <- pos(text.var[i]);if (i%%gc.rate==0) gc();return(x)}))
test
#1 lapply(seq_len(ntv), function(i) {\n x <- pos(text.var[i])\n if (i%%gc.rate == 0) \n gc()\n return(x)\n})
#2 parLapply(cl, seq_len(ntv), function(i) {\n x <- pos(text.var[i])\n if (i%%gc.rate == 0) \n gc()\n return(x)\n})
# replications elapsed relative user.self sys.self user.child sys.child
#1 100 20.03 3.453448 20.31 0.05 NA NA
#2 100 5.80 1.000000 0.22 0.03 NA NA
> cl
socket cluster with 2 nodes on host ‘localhost’