首页 > 解决方案 > 如何正确传递点、点、点参数

问题描述

我正在做这样的事情

library(microbenchmark)
library(tidyverse)

f1 = function(n=100) rnorm(n)

f2 = function(n=100, shape1=1, shape2=0.1) rbeta(n, shape1, shape2)

f3 = function(n=100, shape=1) rgamma(n, shape)

maxdif = 1e6
mb = microbenchmark(f1(100), f2(100), f3(100), times=1)
if(max(abs(mb$time - lead(mb$time)), na.rm=TRUE)<maxdif) mb = 
  microbenchmark(f1(100), f2(100), f3(100), times=10)
mb$time
# [1] 1927396 1876079 1660118   32074   20528   42338   25659   23094   35923   37633
# [11]   16251   39344   27797   38061   13258   12830   38061   13685   13258   23094
# [21]   13686   25232   37633   24377   20528   12830   38061   14113   12402   35495

到目前为止,一切对我来说都很清楚,正如预期的那样。但是,如果我用一个函数括起来

fComp = function(..., times, maxdif){
  mb = microbenchmark(..., times=1)
  if(max(abs(mb$time - lead(mb$time)), na.rm=TRUE)<maxdif) mb = 
      microbenchmark(..., times=times)
  mb
}

mb = fComp(f1(100), f2(100), f3(100), times=10, maxdif = 1e6)
mb$time
# [1]  5988 29508   856   429   429     1     1     1   428     0   428   428     0
# [14]   428     1     1   428     0     1     0     1   429     1     1     0   428
# [27]     0   428     1   429

这是一件很奇怪的事情。

我的猜测是它是关于传递...参数的。不幸的是,我不知道如何正确解码...以获得所需的(如上)效果。

我将不胜感激任何提示。

标签: rfunction

解决方案


似乎问题来自使用...两次。我认为它试图防止表达式被多次评估,这通常可能是您想要的,但在基准测试的情况下,您实际上确实希望多次评估同一个表达式。这是一个解决方法

fComp = function(..., times, maxdif){
  exprs <- match.call(expand.dots = FALSE)$...
  mb = microbenchmark(list=exprs, times=1)
  if(max(abs(mb$time - lead(mb$time)), na.rm=TRUE)<maxdif) mb = 
    microbenchmark(list=exprs, times=times)
  mb
}

我们match.call用来获取传入的未计算表达式...。然后我们将这些参数传递给microbenchmark()vialist=参数而不是使用.... 这似乎避免了这种优化。

此方法还保留了输出中的表达式名称

fComp(f1(100), f2(100), f3(100), times=10, maxdif = 1e6)
Unit: microseconds
    expr  min   lq  mean median   uq  max neval
 f1(100)  8.4  8.7  9.29   9.05  9.6 11.2    10
 f2(100) 25.1 25.7 28.40  25.95 27.5 46.9    10
 f3(100) 13.5 16.3 18.09  17.85 20.3 23.5    10

推荐阅读