微基准测试结果检查失败,因为data.table已被引用更改。

3

有一些在 SO 上的答案进行了时间比较,但是没有检查结果。然而,我更喜欢看到一个表达式是否正确,并且速度快。

microbenchmark包支持使用check参数实现这一点。不幸的是,在通过引用更改 data.table 的表达式中,检查会失败,即检查无法识别结果已经不同。

Case 1: data.table表达式中,检查按预期工作的情况

library(data.table)
library(microbenchmark)

# minimal data.table 1 col, 3 rows
dt <- data.table(x = c(1, 1, 10))

# define check function as in example section of help(microbenchmark)
my_check <- function(values) {
  all(sapply(values[-1], function(x) identical(values[[1]], x)))
}

基准测试案例旨在返回不同的结果。因此,
microbenchmark(
  f1 = dt[, mean(x)],
  f2 = dt[, median(x)],
  check = my_check
)

按预期返回错误消息:

错误:输入表达式不等同。

情况2: data.table表达式未通过检查

现在,表达式已修改为通过引用更改dt。请注意,仍然使用相同的检查函数。

microbenchmark(
  f1 = dt[, y := mean(x)],
  f2 = dt[, y := median(x)],
  check = my_check
)

返回现在

 expr     min      lq     mean   median       uq     max neval cld
   f1 576.947 625.174 642.9820 640.7110 661.1870 732.391   100  a 
   f2 602.022 658.384 684.7076 678.9975 694.0825 978.600   100   b

因此,尽管这两个表达式不同,但结果的检查在此处失败了。(时间无关紧要。)

我明白,检查失败是因为参考已更改dt。因此,比较每个表达式的结果时,总是引用最后更改状态中的相同对象。

问题

如何修改检查函数和/或表达式,使得即使在通过引用更改data.table的情况下,检查也能可靠地检测到不同的结果?

1个回答

4

最简单的方法是使用copy()

microbenchmark(
    f1 = copy(dt)[, y := mean(x)],
    f2 = copy(dt)[, y := median(x)],
    check = my_check, times=1L
)
# Error: Input expressions are not equivalent.

在这里加入copy(dt)可以让我们了解复制所花费的时间(如果需要,我们总是可以从f1f2的运行时间中减去这个时间)。

microbenchmark(
    f1 = copy(dt)[, y := mean(x)],
    f2 = copy(dt)[, y := median(x)],
    f3 = copy(dt),
    times=10L
)
# Unit: microseconds
#  expr     min      lq     mean   median      uq     max neval cld
#    f1 298.690 306.508 331.6364 315.1400 347.788 414.264    10   b
#    f2 319.075 322.475 373.3873 329.3895 336.268 746.134    10   b
#    f3  19.180  19.750  28.3504  25.1745  26.111  70.016    10   a 

1
非常感谢,这是一个简单明了的解决方案,简洁易实现。对于单独基准测试copy()的提示再加2分。 - Uwe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接