9

通常、ベンチマークを実行するときは、ステートメントを で囲みますexpression。最近、(a) そうしないか、(b)quote式の代わりに使用することが提案されました。

ステートメントをラップすることには、次の 2 つの利点があります。

  • ステートメント全体と比較すると、より簡単に交換できます。
  • 入力のリストを重ねて、それらの結果を比較できます

expressionしかし、さまざまな方法を調べているうちに、3 つの方法 ( でラップする、 でラップするquote、またはまったくラップしない)の間に矛盾があることに気付きました。

問題は
、なぜ不一致なのかということです。
(ラップインquoteは実際には呼び出しを評価しないようです。)

例:

# SAMPLE DATA
  mat <-  matrix(sample(seq(1e6), 4^2*1e4, T), ncol=400) 

# RAW EXPRESSION TO BENCHMARK IS: 
  # apply(mat, 2, mean)

# WRAPPED EXPRESSION: 
  expr <- expression(apply(mat, 2, mean))
  quot <- quote(apply(mat, 2, mean))

# BENCHMARKS
  benchmark(raw=apply(mat, 2, mean), expr, quot)[, -(7:8)]
  #    test replications elapsed relative user.self sys.self
  #  2 expr          100   1.269       NA     1.256    0.019
  #  3 quot          100   0.000       NA     0.001    0.000
  #  1  raw          100   1.494       NA     1.286    0.021


# BENCHMARKED INDIVIDUALLY 
  benchmark(raw=apply(mat, 2, mean))[, -(7:8)]
  benchmark(expr)[, -(7:8)]
  benchmark(quot)[, -(7:8)]

  # results
  #    test replications elapsed relative user.self sys.self
  #  1  raw          100   1.274        1      1.26    0.018
  #    test replications elapsed relative user.self sys.self
  #  1 expr          100   1.476        1     1.342    0.021
  #    test replications elapsed relative user.self sys.self
  #  1 quot          100   0.006        1     0.006    0.001
4

1 に答える 1

7

あなたの問題は、式でquoteはなく を生成することですcall。そのため、ベンチマークへの呼び出し内に、評価する式がありません。

`call を評価すると、実際に評価され、タイミングは合理的です。

class(quot)
[1] "call"
>class(expr)
[1] "expression"


 benchmark(raw=apply(mat, 2, mean), expr, eval(quot))[, -(7:8)]
        test replications elapsed relative user.self sys.self
3 eval(quot)          100    0.76    1.000      0.77        0
2       expr          100    0.83    1.092      0.83        0
1        raw          100    0.78    1.026      0.78        0

一般に、ベンチマークしたい呼び出し/プロセスを含む関数を作成する傾向があります。結果を値に代入するなどを含めることをお勧めします。

例えば

 raw <- function() {x <- apply(mat, 2, mean)}

その場合、 によってわずかに改善されているように見えeval(quote(...))ます。

benchmark(raw(), eval(quote(raw()))

                test replications elapsed relative user.self sys.self 
2 eval(quote(raw()))          100    0.76    1.000      0.75     0.01        
1              raw()          100    0.80    1.053      0.80     0.00        

ただし、多くの場合、これらの小さな違いは関数のオーバーヘッドが原因である可能性があり、パフォーマンスがより大きな問題にどのようにスケーリングするかを反映していない場合があります。ソリューションのベンチマークに関する多くの質問を参照してください。data.table少数のレプリケーションを使用していますが、ビッグ データはパフォーマンスをより適切に反映している可能性があります。

于 2012-12-04T22:38:14.040 に答える