0

ご存知のとおり、Rは大規模な分析を実行するための最も効率的なプラットフォームではありません。3つのパラメータを含む大きなデータフレームがある場合:

GROUP   X  Y
A       1  2
A       2  2
A       2  3
...
B       1  1
B       2  3
B       1  4
...
millions of rows

そして、各グループで計算を実行し(たとえば、X、Yでピアソンのrを計算)、結果を新しいデータフレームに格納したかったので、次のように実行できます。

df = loadDataFrameFrom( someFile )
results = data.frame()
for ( g in unique( df$GROUP)) ){
    gdf <- subset( df, df$GROUP == g )
    partialRes <- slowStuff( gdf$X,gdf$Y )
    results = rbind( results, data.frame( GROUP = g, RES = partialRes ) )
}
// results contains all the results here.
useResults(results)

明らかな問題は、強力なマルチコアマシンであっても、これが非常に遅いことです。

私の質問は次のとおりです。たとえば、グループごとまたはグループのブロックごとに個別のスレッドを使用して、この計算を並列化することは可能ですか?この単純な分割統治問題を解決するためのクリーンなRパターンはありますか?

ありがとう、Mulone

4

3 に答える 3

6

まず、Rは必ずしも遅いとは限りません。その速度は、他の言語と同じように、正しく使用することに大きく依存します。あまり変更せずにコードを高速化できることがいくつかありますresults。開始する前にdata.frameを事前に割り当てます。data.frameの代わりにリストと行列またはベクトル構造を使用します。使用するように切り替えますdata.table; リストは続きますが、RInfernoは始めるのに最適な場所です。

また、こちらもご覧ください。マルチコアマシンを活用する方法についての優れた要約を提供します。

「クリーンなRパターン」は、Hadley Wickamがplyrパッケージを使用して簡潔に解決しました。具体的には、次のddplyとおりです。

library(plyr)
library(doMC)
registerDoMC()
ddply(df, .(GROUP), your.function, .parallel=TRUE)

ただし、必ずしも高速ではありません。次のようなものを使用できます。

library(parallel)
mclapply(unique(df$GRUOP), function(x, df)  ...)

foreachまたは最後に、パッケージを使用できます。

foreach(g = unique(df$Group), ...) %dopar$ {
   your.analysis
}
于 2012-05-04T16:15:08.337 に答える
5

私のコメントをバックアップするには:1000万行、26グループ。シングルコア3.3GhzCPUで3秒未満で完了。ベースRのみを使用します。並列化は必要ありません。

> set.seed(21)
> x <- data.frame(GROUP=sample(LETTERS,1e7,TRUE),X=runif(1e7),Y=runif(1e7))
> system.time( y <- do.call(rbind, lapply(split(x,x$GROUP),
+     function(d) data.frame(GROUP=d$GROUP[1],cor=cor(d$X,d$Y)))) )
   user  system elapsed 
   2.37    0.56    2.94 
> y
  GROUP           cor
A     A  2.311493e-03
B     B -1.020239e-03
C     C -1.735044e-03
D     D  1.355110e-03
E     E -8.027199e-04
F     F  8.234086e-04
G     G  2.337217e-04
H     H -5.861781e-04
I     I  7.799191e-04
J     J  1.063772e-04
K     K  7.174137e-04
L     L  4.151059e-04
M     M  4.440694e-04
N     N  2.568411e-03
O     O -3.827366e-04
P     P -1.239380e-03
Q     Q -1.057020e-03
R     R  1.079676e-03
S     S -1.819232e-03
T     T -3.577533e-04
U     U -1.084114e-03
V     V  6.686503e-05
W     W -1.631912e-03
X     X  8.668508e-04
Y     Y -6.460281e-04
Z     Z  1.614978e-03

ちなみに、並列化は、slowStuff関数がボトルネックである場合にのみ役立ちます。rbindで同様のことを行わない限り、ループでの使用がボトルネックになる可能性がありますslowStuff

于 2012-05-04T16:35:13.067 に答える
2

あなたの遅さは、Rでの非Rプログラミングに一部起因していると思います。以下は、グループごとの相関関係を示し(mtcarsデータセットを使用し、それをcylグループで割った)、かなり速く実行します。

by(mtcars, mtcars$cyl, cor)
于 2012-05-04T16:20:33.193 に答える