由工厂函数构造的“微基准”函数
`microbenchmark` functions constructed by a factory function
我有一个函数根据一些特定的参数构造另一个函数:
factory <- function(param) {
# some long computation…
cached.matrix = rnorm(param)
# return function that uses cached data
function(other) {
cached.matrix * cached.matrix + other
}
}
现在,我想使用 microbenchmark
包对 factory
函数针对各种参数生成的函数进行基准测试。 microbenchmark
函数接受一个表达式,而不是一个函数,经过一些实验我注意到下面的 do.call
和 call
似乎有效:
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', …)
更简单的方法来收集像这样参数化的函数的基准测试结果?
我将展示另一条可能的路线。你所做的是构造未计算的表达式,而我将把 microbenchmark
调用包装到一个函数中并使用 outer
产生所需的分解。
我隐含地假设您想要遍历两个维度(在您的示例中,param
和 other
)。我构建了自己的函数工厂:
factory <- function(param) {
x <- rnorm(param)
function(mat) {
t(x) %*% mat %*% x
}
}
现在我想遍历 param
和 mat
。为了让它更有趣,让 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
的完整信息集(使用来自我的 的列表包装 hack):
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
编辑:作为对下面评论的回应,这里介绍了如何仅测量对从工厂发出的函数的调用。
# 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
})
我有一个函数根据一些特定的参数构造另一个函数:
factory <- function(param) {
# some long computation…
cached.matrix = rnorm(param)
# return function that uses cached data
function(other) {
cached.matrix * cached.matrix + other
}
}
现在,我想使用 microbenchmark
包对 factory
函数针对各种参数生成的函数进行基准测试。 microbenchmark
函数接受一个表达式,而不是一个函数,经过一些实验我注意到下面的 do.call
和 call
似乎有效:
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', …)
更简单的方法来收集像这样参数化的函数的基准测试结果?
我将展示另一条可能的路线。你所做的是构造未计算的表达式,而我将把 microbenchmark
调用包装到一个函数中并使用 outer
产生所需的分解。
我隐含地假设您想要遍历两个维度(在您的示例中,param
和 other
)。我构建了自己的函数工厂:
factory <- function(param) {
x <- rnorm(param)
function(mat) {
t(x) %*% mat %*% x
}
}
现在我想遍历 param
和 mat
。为了让它更有趣,让 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
编辑:作为对下面评论的回应,这里介绍了如何仅测量对从工厂发出的函数的调用。
# 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
})