9

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

1 回答 1

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

一般来说,我倾向于创建一个包含我希望进行基准测试的调用/进程的函数。请注意,最好包含诸如将结果分配给值之类的内容。

例如

 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 回答