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

时间:2012-12-04 22:31:11

标签: r expression benchmarking

通常,当我运行基准测试时,我将我的语句包装在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

1 个答案:

答案 0 :(得分: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解决方案基准测试的许多问题,但大数据可能更能反映性能。