通常,当我运行基准测试时,我将我的语句包装在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
答案 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
解决方案基准测试的许多问题,但大数据可能更能反映性能。