`microbenchmark`函数由工厂函数构造

时间:2015-04-09 14:39:11

标签: r microbenchmark

我有一个函数根据一些特定的参数构造另一个函数:

factory <- function(param) {
    # some long computation…
    cached.matrix = rnorm(param)

    # return function that uses cached data
    function(other) {
        cached.matrix * cached.matrix + other
    }
}

现在,我想使用factory包对microbenchmark函数为各种参数生成的函数进行基准测试。 microbenchmark函数使用表达式,而不是函数,经过一些实验后,我注意到以下与do.callcall的舞蹈似乎有效:

params <- seq(5, 100, 5)
list.of.expressions <- sapply(
    params,
    function(param) call('do.call', factory(param), list(7)))
names(list.of.expressions) <- sprintf("f%04d", params)
mb.results <- microbenchmark(list=list.of.expressions, times=10)

是否有一种比call('do.call', …)更简单的方法来收集像这样参数化的函数基准测试结果?

1 个答案:

答案 0 :(得分:1)

我要展示另一条可能的路线。你所做的是构建未评估的表达式,而我将把microbenchmark调用包装成一个函数并使用outer来产生所需的细分。

我隐含地假设您希望迭代两个维度(在您的示例中,paramother)。我已经建立了自己的功能工厂:

factory <- function(param) {
  x <- rnorm(param)
  function(mat) {
    t(x) %*% mat %*% x
  }
}

现在我想迭代parammat。为了让它更有趣,让mat以某种方式依赖于param。如果情况并非如此,只需忽略mat作为一个函数:它可以是一个向量。

params <- seq(10, 50, 10)
mat1 <- function(param) {diag(param)}
mat2 <- function(param) {matrix(runif(param^2), param)}

这里有outer的功能,以及通话本身:

test_factory_med <- Vectorize(function(param, matf) {
         summary(microbenchmark(factory(param)(matf(param))))$median
})
median_tests <- outer(params, c(mat1, mat2), 
                      FUN = function(p, m) test_factory_med(p, m))

colnames(median_tests) <- c("mat1", "mat2")
rownames(median_tests) <- params
median_tests
#      mat1     mat2
#10 15.3150  22.6720
#20 18.6180  36.6355
#30 22.2220  57.9560
#40 27.3265  88.5860
#50 32.7320 129.1250

您可以通过从microbenchmark返回一个列表来保留test_factory_all <- Vectorize(function(param, matf) { list( list(param = param, matf = mat, microbenchmark(factory(param)(matf(param))))) }) all_tests <- outer(params, c(mat1, mat2), FUN = function(p, m) test_factory_all(p, m)) all_tests[1, 1] #[[1]] #[[1]]$param #[1] 10 # #[[1]]$matf #function (param) #{ # diag(param) #} # #[[1]][[3]] #Unit: microseconds # expr min lq mean median uq max neval # factory(param)(matf(param)) 14.414 15.315 17.17081 15.916 16.516 88.586 100 中的一整套信息(包含来自recent question的列表包装黑客):

# exclude costs for running factory
test_factory_med1 <- Vectorize(function(param, matf) {
         f <- factory(param)
         summary(microbenchmark(f(matf(param))))$median
})

# exclude costs for both running factory and constructing parameter
test_factory_med2 <- Vectorize(function(param, matf) {
         f <- factory(param)
         m <- matf(param)
         summary(microbenchmark(f(m)))$median
})

编辑:在回复下面的评论时,以下是如何仅测量从工厂发出的函数的调用。

{{1}}