/ / doMC в R и foreach loop не работи - windows, r, foreach, паралелна обработка, domc

doMC в R и foreach цикъл не работи - прозорци, r, foreach, паралелна обработка, domc

Опитвам се да получа пакета foreach за паралелна обработка в R работа и имам няколко проблема:

Пакетът doMC, който е необходим, за да се направи foreachработа не съществува на CRAN за Windows. Някои блогове предполагат, че доSNOW трябва да вършат същата работа. Въпреки това, когато стартирам командата foreach с doSNOW, %dopar% изглежда не работи по-бързо от %do%, Всъщност тя е много по-бавна. Моят CPU е Intel i7 860 @ 2.80GHz с 8 GB RAM. По-долу е кодът ми:

##Run example in 1 core
require(foreach)
require(doSNOW)
x= iris[which(iris[,5] != "setosa"),c(1,5)]
trials = 10000
system.time({
r= foreach(icount(trials), .combine=cbind) %do% {
ind=sample(100,100,replace=TRUE)
results1 = glm(x[ind,2]~x[ind,1],family=binomial(logit))
coefficients(results1)
}
})[3]
#  elapsed
#  37.28

# Same example in 2 cores
registerDoSNOW(makeCluster(2,type="SOCK"))
getDoParWorkers()
trials = 10000
system.time({
r= foreach(icount(trials), .combine=cbind) %dopar% {
ind=sample(100,100,replace=TRUE)
results1 = glm(x[ind,2]~x[ind,1],family=binomial(logit))
coefficients(results1)
}
})[3]
# elapsed
#  108.14

Преинсталирах всички необходими пакети, но все пак имах същите проблеми. Ето изхода:

sessionInfo()

#R version 2.15.1 (2012-06-22)
#Platform: i386-pc-mingw32/i386 (32-bit)

#locale:
#[1] LC_COLLATE=English_United States.1252
#[2] LC_CTYPE=English_United States.1252
#[3] LC_MONETARY=English_United States.1252
#[4] LC_NUMERIC=C
#[5] LC_TIME=English_United States.1252

#attached base packages:
#[1] parallel  stats     graphics  grDevices datasets  utils     methods
#[8] base

#other attached packages:
#[1] doParallel_1.0.1 codetools_0.2-8  doSNOW_1.0.6     snow_0.3-10
#[5] iterators_1.0.6  foreach_1.4.0    rcom_2.2-5       rscproxy_2.0-5

#loaded via a namespace (and not attached):
#[1] compiler_2.15.1 tools_2.15.1

Отговори:

4 за отговор № 1

По-добре е да използвате Windows doParallel():

require(foreach)
require(doParallel)
cl <- makeCluster(6) #use 6 cores, ie for an 8-core machine
registerDoParallel(cl)

След това ти пуснете foreach() %dopar% {}

EDIT: OP споменава все още виждам проблема, така че включвам и точния ми код. Работещи на 4-ядрен Windows7 VM, R 2.15.1 32-битов, само позволява doParallel да използвам 3 от моите ядра:

require(foreach)
require(doParallel)
cl <- makeCluster(3)
registerDoParallel(cl)

x= iris[which(iris[,5] != "setosa"),c(1,5)]

trials = 1000
system.time(
foreach(icount(trials), .combine=cbind) %do%
{
ind=sample(100,100,replace=TRUE)
results1 = glm(x[ind,2]~x[ind,1],family=binomial(logit))
results1 = glm(x[ind,2]~x[ind,1],family=binomial(logit))
results1 = glm(x[ind,2]~x[ind,1],family=binomial(logit))
results1 = glm(x[ind,2]~x[ind,1],family=binomial(logit))
coefficients(results1)
})[3]

system.time(
foreach(icount(trials), .combine=cbind) %dopar%
{
ind=sample(100,100,replace=TRUE)
results1 = glm(x[ind,2]~x[ind,1],family=binomial(logit))
results1 = glm(x[ind,2]~x[ind,1],family=binomial(logit))
results1 = glm(x[ind,2]~x[ind,1],family=binomial(logit))
results1 = glm(x[ind,2]~x[ind,1],family=binomial(logit))
coefficients(results1)
})[3]

В моя случай получавам 17.6 сек за %do% и 14.8 сек за %dopar%, Гледайки изпълнението на задачите, изглежда, че голяма част от времето за изпълнение е cbind, което е често срещан проблем, протичащ паралелно. В собствените си симулации направих обичайна работа, за да запазя подробните си резултати като част от паралелната задача, вместо да ги върна foreach, за да премахнете тази част от режима. YMMV.


3 за отговор № 2

Знам, че това е по-стар въпрос, но дойдохпо време на търсенето на нещо друго и мислех, че ще добавя решението си. Смятам, че е по-ефективно да се раздели общият брой на изпитванията на отделни групи опити (броят на групите е равен на броя на процесорните ядра), Опитвам се да паралелизира всички тестове едновременно и да се справяме с всички режийни операции.

require(doParallel)

x <- iris[which(iris[,5] != "setosa"),c(1,5)]
trials <- 10000

# example using a single core
t1 <- system.time({
r1 <- foreach(icount(trials), .combine=cbind) %do% {
ind <- sample(100,100,replace= TRUE)
results1 <- glm(x[ind,2]~x[ind,1],family=binomial(logit))
coefficients(results1)
}
})[3]

# example using 4 cores and parallelizing each model trial
nCores <- 4
cl <- makeCluster(nCores)
registerDoParallel(cl)

t2 <- system.time({
r2 <- foreach(icount(trials), .combine=cbind) %dopar% {
ind <- sample(100,100,replace= TRUE)
results1 <- glm(x[ind,2]~x[ind,1],family=binomial(logit))
coefficients(results1)
}
})[3]

# example using 4 cores and parallelizing a group of trial runs
trialsPerCore <- as.integer(ceiling(trials / nCores)) # number of trials
# do to on each core
# function to do a single model run
model <- function(x) {
ind <- sample(100,100,replace= TRUE)
results1 <- glm(x[ind,2]~x[ind,1],family=binomial(logit))
coefficients(results1)
}
# function producing a group of model runs
modelRun <- function(trials, x) {
replicate(trials, model(x))
}
# call the model run for each core
t3 <- system.time(
r3 <- foreach(icount(nCores), .combine= cbind) %dopar% modelRun(trialsPerCore, x)
)[3]

stopCluster(cl)

Времето за изпълнение на четириядрен процесор с честота 3.4 GHz и Ubuntu 12.04:

> t1
elapsed
34.5
> t2
elapsed
26.5
> t3
elapsed
8.295

2 за отговор № 3

Това не е нетипично за този тип паралелизъм и може да зависи от операционната система. Имах подобен резултат като теб, но когато направих една глупава промяна в кода

require(foreach)
require(doSNOW)

x= iris[which(iris[,5] != "setosa"),c(1,5)]

trials = 1000
system.time(
foreach(icount(trials), .combine=cbind) %do%
{
ind=sample(100,100,replace=TRUE)
results1 = glm(x[ind,2]~x[ind,1],family=binomial(logit))
results1 = glm(x[ind,2]~x[ind,1],family=binomial(logit))
results1 = glm(x[ind,2]~x[ind,1],family=binomial(logit))
results1 = glm(x[ind,2]~x[ind,1],family=binomial(logit))
coefficients(results1)
})[3]


registerDoSNOW(  makeCluster(2,type="SOCK"))
getDoParWorkers()
trials = 1000
system.time(
foreach(icount(trials), .combine=cbind) %dopar%
{
ind=sample(100,100,replace=TRUE)
results1 = glm(x[ind,2]~x[ind,1],family=binomial(logit))
results1 = glm(x[ind,2]~x[ind,1],family=binomial(logit))
results1 = glm(x[ind,2]~x[ind,1],family=binomial(logit))
results1 = glm(x[ind,2]~x[ind,1],family=binomial(logit))
coefficients(results1)
})[3]

да симулирам тежка работа в foreach, имам aпрекъсване и за двете. Това е цената на режийните. Наскоро имах подобен случай и се справих директно с MPI, който има много по-ниски режийни, но е много по-сложен за използване (Dirk няма да се съгласи, предполагам). (Променете това на "много по-малко елегантно".