2016-07-21 21 views
0

私はRが新しく、最近、特定の値を持つリストの要素のインデックスを見つける必要がありました。私はforeachを使用して操作を高速化しようとし、これを行う2つの方法を比較しました。単純なR foreachの例

library("iterators") 
library("foreach") 
library("doParallel") 
a <- 1:200000 
b <- sample(1:200000,100000,replace=TRUE) 
registerDoParallel() 
getDoParWorkers(); #to see the number of cores 
system.time(unlist(lapply(b,function(x) which(a==x)))) 
system.time(foreach(i<-iter(b),.combine='c') %dopar% { which(a==b) }) 

出力::私は思ったんだけど

Loading required package: parallel 
[1] 32 
    user system elapsed 
124.648 7.460 132.114 
    user system elapsed 
402.076 59.164 55.260 

:1以下のコードでは「」リストと「b」は、インデックスが、我々は「A」の中に取得する値がされています)naively、なぜこの動作が遅いのですか?私はチェックしていないが、私はスクリプト言語が同じことをはるかに速くできると思うだろう。 2)操作が非常にうまく並行して行われるべきではないが、私は32コアを利用できるので、予想よりも長くかかるようだ。 3)実際には、行列の行、すなわちforeach(i = 0、1)を%iter%{#stuff}で反復処理しています。私の理解は、このアプローチは、各コアに行列全体を送信しないので、このアプローチが最善であるということです。各コアが受け取っているデータを確認することで確認する方法はありますか?

+0

私は専門家ではないので、間違っている可能性があります:一般に、コンパイルされた言語は翻訳された言語よりも高速です(実際には、毎回解釈されるべきであり、その結果、時間が失われる)。それで、Rのベクトル化は他の言語よりも遅いにもかかわらず役に立ちます...しかし、私の謙虚な意見(私はRもかなり新しいです)では、コンパイルされたベクトル化されていない言語よりも、Rで書く時間が大幅に減ります。 ) – Eugen

答えて

0

1e5 * 2e5の比較を行います。これには時間がかかることは間違いありません。

個々のwhich(a==x)はそれほど時間がかかりませんし、各繰り返しをワーカーに別々に送信すると、並列化のオーバーヘッドが大きくなります。反復の束を送る方がはるかに良いでしょう。あなたはmclapplyでちょうどそれを行うことができますWindows以外のシステムでは:

a <- 1:20000 
b <- sample(1:20000,10000,replace=TRUE) 

library(parallel) 
system.time(res1 <- unlist(lapply(b,function(x) which(a==x)))) 
# user  system  elapsed 
#0.597  0.178  0.789 
system.time(res2 <- unlist(mclapply(b,function(x) which(a==x), 
            mc.preschedule = TRUE, mc.cores = 3))) 
# user  system  elapsed 
#0.004  0.022  0.325 
all.equal(res1, res2) 
#[1] TRUE 

3について):(最高は行列代数だろう)並列化よりももっと良い方法があるかもしれませんが、それはあなたの#stuffに依存します。

+0

ありがとう、並列化のオーバーヘッドは、私が考えに慣れてきたものです。 – nak3c