为什么我的基准测试会随着样本量的增加而出现一些振荡?

问题描述 投票:0回答:1

我用

microbenchmark::microbenchmark()
为两个函数制定了基准,并改变了函数中输入的样本大小。在这样做的过程中,我注意到每次性能时间都会出现一些波动。这是一个简单 while 函数的基准图:

fun <- function(n){
  i <- 1
  while (n > i) {
    i <- i + 1
  }
}

x 轴是样本大小 (

n
),以对数刻度表示,y 轴显示中值执行时间。我预计当
n
增加时,运行该函数的时间应该增加,但事实并非如此。我多次运行代码,总是得到相同的图片:存在一些振荡。但为什么呢?

用于生成数据和绘图的完整代码是:

# Load libraries.
library(magrittr)
library(ggplot2)
# Define some function.
fun <- function(n){
  i <- 1
  while (n > i) {
    i <- i + 1
  }
}
# Set sample sizes.
n <- c(10, 100, 1000, 10000, 100000, 1000000)
# Run per predefined sample sizes..
results<- lapply(n, function(n_i){
  results_i <- microbenchmark::microbenchmark(fun(n= n_i),
                                          times= 1000)

  data.frame(n= n_i,
             time= summary(results_i)$median)
}) %>%
  do.call("rbind.data.frame", .)

# Produce a plot.
results %>%
  ggplot(data= ., mapping= aes(x= n, y= time)) +
  geom_smooth(se= FALSE) +
  geom_point() +
  scale_x_continuous(trans='log10') +
  theme_minimal()
r microbenchmark
1个回答
0
投票

事实并非如此。您的问题是,当您执行

time = summary(results_i)$median)
时,您正在提取中位时间的数值,但没有考虑时间单位的变化。比较:

microbenchmark::microbenchmark(
    fun(n= 1e4),
    times= 10
)
# Unit: microseconds
#            expr   min     lq    mean  median     uq    max neval
#  fun(n = 10000) 959.1 1111.6 1141.56 1150.25 1218.2 1235.1    10

但是,当您将其提高到

1e5
时,您现在看到的是毫秒:

microbenchmark::microbenchmark(
    fun(n= 1e5),
    times= 10
)
# Unit: milliseconds
#            expr    min     lq    mean  median      uq     max neval
#  fun(n = 1e+05) 5.9059 6.7059 9.54744 10.2045 11.1353 13.9593    10

您可以重新运行模拟,根据

time
列自行计算中位数,以确保单位相同并获得预期结果:

results <- lapply(
    n, 
    function(n_i) {
       microbenchmark::microbenchmark(
        fun(n= n_i),
        times= 100
      ) |> 
      transform(n = n_i)
}) |>
  do.call(rbind, args = _)

results |>
    dplyr::summarise(
        median = median(time),
        .by = n
    ) |>
  ggplot(mapping= aes(x= n, y= median)) +
  geom_smooth(se = FALSE)
  geom_point() +
  scale_x_continuous(trans='log10') +
  theme_minimal()

© www.soinside.com 2019 - 2024. All rights reserved.