Опитвам се да получа пакета 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 няма да се съгласи, предполагам). (Променете това на "много по-малко елегантно".