4

R での並列処理用の foreach パッケージを取得しようとしていますが、いくつかの問題があります。

foreach を機能させるために必要な doMC パッケージは、CRAN for Windows には存在しません。一部のブログでは、代わりに doSNOW が同じ仕事をするべきだと示唆しています。ただし、doSNOW を使用して foreach コマンドを実行すると、%dopar%より速く動作しないようです%do%。実際、それははるかに遅いです。私の CPU は、8 GB の RAM を搭載した Intel i7 860 @ 2.80GHz です。以下は私のコードです:

##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

3 に答える 3

4

Windowsで使用する方がよいでしょうdoParallel()

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

次に、foreach() %dopar% {}

編集:OPはまだ問題が見られると述べたので、私の正確なコードを含めてください。4コアのWindows7 VM、R 2.15.1 32ビットで実行し、3つのコアのみdoParallelを使用できます:

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。

于 2012-07-23T17:50:39.870 に答える
2

これは、このタイプの並列処理では珍しいことではなく、オペレーティング システムに依存する場合があります。あなたと同様の結果が得られましたが、コードにばかげた変更を加えたとき

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 で重い作業をシミュレートするために、両方の損益分岐点を得ました。これは間接費の価格です。最近、同様のケースがあり、オーバーヘッドがはるかに少ないMPIで直接処理しましたが、使用するのははるかに複雑です(Dirkは同意しないと思います)。(これを「はるかにエレガントではない」に変更します。

于 2012-07-23T17:53:30.977 に答える