【问题标题】:How to correctly pass the dot, dot, dot argument如何正确传递点、点、点参数
【发布时间】:2021-11-30 11:31:31
【问题描述】:

我正在做这样的事情

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

这很奇怪。

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

如有任何提示,我将不胜感激。

【问题讨论】:

    标签: r function


    【解决方案1】:

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

    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 来获取... 中传递的未计算表达式。然后我们通过list= 参数而不是使用... 将这些参数传递给microbenchmark()。这似乎避免了这种优化。

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

    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
    

    【讨论】:

      【解决方案2】:

      一种方法是将... 的顺序更改为最后一个参数,这样就可以了

      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
      }
      

      -测试

      fComp(times=10, maxdif = 1e6, f1(100), f2(100), f3(100))
      Unit: microseconds
       expr      min       lq     mean   median       uq      max neval
        ..1 1957.235 1957.235 1957.235 1957.235 1957.235 1957.235     1
        ..2  101.801  101.801  101.801  101.801  101.801  101.801     1
        ..3  170.926  170.926  170.926  170.926  170.926  170.926     1
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-04-30
        • 1970-01-01
        • 1970-01-01
        • 2014-07-21
        • 2013-03-14
        • 1970-01-01
        相关资源
        最近更新 更多