基准测试:使用`表达式``quote`或两者都没有

Ric*_*rta 9 benchmarking expression r

通常,当我运行基准测试时,我将我的语句包装起来expression.最近,有人建议(a)不这样做或(b)使用quote而不是表达.

我发现包装语句有两个好处:

  • 与整个陈述相比,它们更容易被换掉.
  • 我可以对输入列表进行讨论,并比较这些结果

然而,在探索不同的方法时,我注意到三种方法之间存在差异(包装expression,包装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
Run Code Online (Sandbox Code Playgroud)

mne*_*nel 7

你的问题是quote不会产生表达式而是a 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
Run Code Online (Sandbox Code Playgroud)

一般来说,我倾向于创建一个包含我希望基准测试的调用/过程的函数.请注意,最好包括将结果分配给值等内容.

例如

 raw <- function() {x <- apply(mat, 2, mean)}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,看起来有一点点改善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        
Run Code Online (Sandbox Code Playgroud)

但通常这些小的差异可能是由于功能的开销,并且可能无法反映性能如何扩展到更大的问题.data.table使用少量复制来查看解决方案基准测试的许多问题,但大数据可能更好地反映性能.