2013-04-12 17 views
12

ブートストラップ機能をスピードアップしたいと思います。私はR 2.14以来、parallelと呼ばれるパッケージがありますが、私はそれがsbにとって非常に難しいと感じています。それを実際に実装するためのコンピュータサイエンスの知識は低いです。たぶん誰かが助けることができます。R並列を使用してブートストラップを高速化する

は、そこでここでは、ブートストラップを持っている:

n<-1000 
boot<-1000 
x<-rnorm(n,0,1) 
y<-rnorm(n,1+2*x,2) 
data<-data.frame(x,y) 
boot_b<-numeric() 
for(i in 1:boot){ 
    bootstrap_data<-data[sample(nrow(data),nrow(data),replace=T),] 
    boot_b[i]<-lm(y~x,bootstrap_data)$coef[2] 
    print(paste('Run',i,sep=" ")) 
} 

目標は、私のPCの複数のコアを活用/並列処理を使用することです。私はWindows上でRを実行しています。ありがとう! (ノアによって返信後)

EDIT

次の構文は、テストのために使用することができる。

library(foreach) 
library(parallel) 
library(doParallel) 
registerDoParallel(cores=detectCores(all.tests=TRUE)) 
n<-1000 
boot<-1000 
x<-rnorm(n,0,1) 
y<-rnorm(n,1+2*x,2) 
data<-data.frame(x,y) 
start1<-Sys.time() 
boot_b <- foreach(i=1:boot, .combine=c) %dopar% { 
    bootstrap_data<-data[sample(nrow(data),nrow(data),replace=T),] 
    unname(lm(y~x,bootstrap_data)$coef[2]) 
} 
end1<-Sys.time() 
boot_b<-numeric() 
start2<-Sys.time() 
for(i in 1:boot){ 
    bootstrap_data<-data[sample(nrow(data),nrow(data),replace=T),] 
    boot_b[i]<-lm(y~x,bootstrap_data)$coef[2] 
} 
end2<-Sys.time() 
start1-end1 
start2-end2 
as.numeric(start1-end1)/as.numeric(start2-end2) 

しかし、私のマシン上で単純なRコードが速いです。これは並列処理の既知の副作用の1つです。つまり、このような「単純なタスク」で時間に追加されるプロセスをフォークするオーバーヘッドが発生しますか?

編集:私のマシンでは、parallelコードは「シンプル」コードよりも約5倍の時間がかかります。この要因は、タスクの複雑さを増やす(例:bootまたはnを増やす)と、明らかに変化しません。だから、コードやマシン(Windowsベースの処理?)に問題があるかもしれません。

答えて

7

私はWindows上parallelバックエンドとforeachをテストしていませんが、私は、これはあなたのために働くだろうと信じて:

library(foreach) 
library(doSNOW) 

cl <- makeCluster(c("localhost","localhost"), type = "SOCK") 
registerDoSNOW(cl=cl) 

n<-1000 
boot<-1000 
x<-rnorm(n,0,1) 
y<-rnorm(n,1+2*x,2) 
data<-data.frame(x,y) 
boot_b <- foreach(i=1:boot, .combine=c) %dopar% { 
    bootstrap_data<-data[sample(nrow(data),nrow(data),replace=T),] 
    unname(lm(y~x,bootstrap_data)$coef[2]) 
} 
+0

ありがとう、私はテスト(上記の編集済みのコード)に提案された構文を和解しました。現在、CPUの100%(つまりすべてのプロセッサ)を使用しています。しかし、これは並列処理なしで行うよりも遅いです(上記を参照)。 – tomka

+0

時間の問題について追加の提案をすることができればすばらしいです。つまり、あなたの提案がスピードアップしないのはなぜですか?ありがとう。 – tomka

+0

Hmm。面白い。私のマシン(8 HTコア、8 GB RAM、Ubuntu 12.04)では、RAMの使用量はほとんどなく、約3.4倍のスピードアップを得ました。私はWindows環境でのマルチスレッドに精通していません。試してみるべきことがいくつかあります: – Noah

8

bootパッケージを試してみてください。最適化されており、引数はparallelです。このパッケージの難題は、作業中のデータを受け入れる統計を計算するための新しい関数と、データを再サンプリングするためのインデックスのベクトルを書く必要があることです。だから、あなたはdataを定義するところから始めて、あなたはこのような何か行うことができます:

# Define a function to resample the data set from a vector of indices 
# and return the slope 
slopeFun <- function(df, i) { 
    #df must be a data frame. 
    #i is the vector of row indices that boot will pass 
    xResamp <- df[i, ] 
    slope <- lm(y ~ x, data=xResamp)$coef[2] 
} 

# Then carry out the resampling 
b <- boot(data, slopeFun, R=1000, parallel="multicore") 

b$tをリサンプリング統計のベクトルであり、そしてbootは簡単にものを行うために素敵な方法の多くを持っている - 例えばplot(b)

のために

パラレルメソッドはプラットフォームによって異なります。 Windowsマシンでは、parallel="snow"を使用する必要があります。

+0

あなたの解決策は私のマシンで25%のようなものでスピードアップしています。それはすばらしい。私が見ている実際のアプリケーションでは、問題ははるかに複雑です。なぜなら、私の関数は、すべてがブートストラップされなければならないパラメータのリストを返すからです。したがって、私はパラレルの直接実装を探しています。 – tomka

+0

@tomka、この場合でも 'boot'はうまく動作します。あなたが書いた関数は、あなたが興味のあるパラメータのベクトルを返すことができます。実際、これはブートの強みの1つです。あなた自身の任意の関数を書く能力です。 –

3

私は主な問題は、あなたには小さなタスクがたくさんあると思います。 idiv機能を使用して私は好き

boot_b <- foreach(b=idiv(boot, chunks=getDoParWorkers()), .combine='c') %dopar% { 
    sapply(1:b, function(i) { 
    bdata <- data[sample(nrow(data), nrow(data), replace=T),] 
    lm(y~x, bdata)$coef[[2]] 
    }) 
} 

:いくつかのケースでは、あなたは少なく、その結果をチャンクタスク、しかし、多くの場合、より効率的であり、マスターと労働者の間で大規模なデータ転送を使用してパフォーマンスを向上させることができますこれについては、あなたが好きな場合b=rep(boot/detectCores(),detectCores())することができます。

関連する問題