14

ブートストラップ関数を高速化したいのですが、それ自体は完全に正常に機能します。R 2.14 から というパッケージがあると読みましたが、parallelsb では非常に難しいと思います。実際に実装するには、コンピュータ サイエンスの知識がほとんどありません。多分誰かが助けることができます。

したがって、ここにブートストラップがあります。

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を実行しています。ありがとう!

編集(ノアからの返信後)

テストには次の構文を使用できます。

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 ベースの処理?)。

4

4 に答える 4

11

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".

于 2013-04-12T19:48:19.107 に答える
8

Windows のバックエンドでテストforeachしていませんが、これでうまくいくと思います。parallel

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])
}
于 2013-04-12T18:50:10.507 に答える
3

主な問題は、小さなタスクがたくさんあることだと思います。場合によっては、タスク チャンクを使用してパフォーマンスを向上させることができます。これにより、マスターとワーカーの間のデータ転送は少なくなりますが、より大きなデータ転送になります。多くの場合、より効率的です。

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]]
  })
}

idivはこれに関数を使用するのが好きですがb=rep(boot/detectCores(),detectCores())、必要に応じて使用できます。

于 2013-04-20T14:12:18.407 に答える