2012-11-16 4 views
6

誰でも、Rでreplicate()関数がどのように機能し、forループを使用するのが効率的かを知っていますか?forループとReplicate()を比較しますか?

例えば、

means <- replicate(100000, mean(rnorm(50))) 

そして...

means <- c() 
for(i in 1:100000) { 
    means <- c(means, mean(rnorm(50))) 
} 

...との間の効率の差がある(私は少し上記のオフ何かを入力したかもしれないが、あなたのアイデアを得ます。 )

答えて

14

コードをベンチマークして、経験的に答えを得ることができます。ベクトルをあらかじめ割り当てておくことで、増加するベクトルの問題を回避するループフレーバーの2つ目も追加しました。 relative列を見ると

repl_function = function(no_rep) means <- replicate(no_rep, mean(rnorm(50))) 
for_loop = function(no_rep) { 
    means <- c() 
    for(i in 1:no_rep) { 
     means <- c(means, mean(rnorm(50))) 
    } 
    means 
} 
for_loop_prealloc = function(no_rep) { 
    means <- vector(mode = "numeric", length = no_rep) 
    for(i in 1:no_rep) { 
     means[i] <- mean(rnorm(50)) 
    } 
    means 
} 

no_loops = 50e3 
benchmark(repl_function(no_loops), 
      for_loop(no_loops), 
      for_loop_prealloc(no_loops), 
      replications = 3) 

         test replications elapsed relative user.self sys.self 
2   for_loop(no_loops)   3 18.886 6.274 17.803 0.894       
3 for_loop_prealloc(no_loops)   3 3.209 1.066  3.189 0.000       
1  repl_function(no_loops)   3 3.010 1.000  2.997 0.000       
    user.child sys.child 
2   0   0                     
3   0   0                     
1   0   0 

、非事前に割り当てループのためには、6.2倍遅くなります。しかし、事前に割り当てられたforループは、replicateと同じくらい速いです。

8

replicatesapplyのラッパーで、それ自体はlapplyのラッパーです。 lapplyは最終的にはCで書かれた関数.Internalであり、インタプリタではなく最適化された方法でループを実行します。効率的なメモリ管理が主な利点です。特に、上記の非常に非効率的なベクターの育成方法と比較してです。

+1

事前に割り当てられたforループは、 'replicate'と同じ速さです。私はそれがコードの大部分がRで費やされているからだと思います。ループ全体を「平均」の周りに再実装します。おそらくC++はかなりスピードアップします。私の答えのベンチマークを参照してください。 –

1

私はreplicateと非常に異なる経験をしており、私も混乱します。上記の理由から、forのパフォーマンスを上回るC書込み関数が期待されていたので、私はRがクラッシュしてラップトップがハングして、forと比べてreplicateを使用するとハングアップすることがよくあります。あなたは以下の機能を実行する場合たとえば、あなたはforループは明らかに速くなり、forループは10反復で速くよりreplicate

system.time(for (i in 1:10) runif(1e7)) 
# user system elapsed 
# 3.340 0.218 3.558 

system.time(replicate(10, runif(1e7))) 
# user system elapsed 
# 4.622 0.484 5.109 

そうであることがわかります。 100回繰り返しても同様の結果が得られます。だから誰でもと比較しての実用的な特権を示す例があれば、私は疑問に思う。

PS私もrunif(1e7)のための関数を作成しましたが、比較では違いはありませんでした。基本的には、replicateの利点を示す例はありませんでした。

1

ベクトル化は、それらの主な違いです。私はこの点を説明するためにトレイを用意します。 Rは、高レベルで解釈されるコンピュータ言語です。それはあなたのための多くの基本的なコンピュータタスクを処理します。あなたは

x <- 2.0 

を書くとき、あなたは

  • 「2.0」が浮動小数点数であることをコンピュータに指示する必要はありません。
  • "x"は数値型データを格納する必要があります。
  • メモリに "5"を入れる場所を見つけなければなりません。
  • メモリ内の特定の場所へのポインタとして "x"を登録する必要があります。

Rこれらは単独で数値化されます。

しかし、このような快適な問題のために、価格があります。低レベルの言語よりも遅いです。

CまたはFORTRANでは、この "テストif"の多くは、プログラムの実行中ではなく、コンパイルステップ中に実行されます。書き込まれた後でも、実行される前にバイナリコンピュータ言語(0/1)に変換されます。これにより、コンパイラは、コンピュータが解釈する最適な方法でバイナリ・マシン・コードを編成することができます。

Rのベクトル化とは何が関係していますか?さて、多くのR関数は実際にはC、C++、FORTRANなどのコンパイル言語で記述され、小さなR "ラッパー"を持っています。これはあなたのアプローチの違いです。 forループは、機械がデータに対して行うべき操作であるtest ifの操作を遅くします。

関連する問題