R Academy · 课时

使用 microbenchmark 进行基准测试

使用 microbenchmark() 对多个实现进行统计比较

第 4 / 4 课13 个步骤

使用 microbenchmark 进行基准测试 是 CoddyKit 上的免费 R Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 R Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 R Academy 课程共包含 4 节课。

为什么使用 microbenchmark?

system.time() 的分辨率为毫秒级,对于快速操作不够可靠。microbenchmark 程序包会将表达式运行数百次,处理预热过程,并报告纳秒级分辨率的统计数据,因此它是比较相似实现的合适工具。

microbenchmark 的基本用法

将带名称的表达式传递给 microbenchmark()。每个参数的名称都会成为输出中的标签。times 参数控制每个表达式的求值次数。

# library(microbenchmark)
# x <- 1:10000
#
# microbenchmark(
#   loop = {
#     s <- 0
#     for (v in x) s <- s + v
#   },
#   vectorized = sum(x),
#   times = 200L
# )

选择 times 参数

重复次数越多,估计结果越稳定,但耗时也越长。一般建议如下:

  • 快速表达式(微秒级):times = 1000L 或更多
  • 中等速度(毫秒级):times = 100L
  • 慢速操作(秒级):times = 10L 或更少

默认值为 times = 100L,这是一个很好的起点。

# library(microbenchmark)
# microbenchmark(
#   fast_op = sqrt(2),
#   times = 10000L   # many reps for a nanosecond-scale operation
# )
# microbenchmark(
#   slow_op = sort(rnorm(1e6)),
#   times = 10L      # fewer reps for second-scale operation
# )

指定 unit 参数

使用 unit 参数,以便用合适的尺度显示结果:

  • 'ns' — 纳秒(用于非常快速的操作)
  • 'us' — 微秒
  • 'ms' — 毫秒
  • 's' — 秒
  • 'relative' — 相对于最快表达式的比值
# library(microbenchmark)
# x <- runif(1000)
#
# microbenchmark(
#   sapply_sqrt = sapply(x, sqrt),
#   vectorized  = sqrt(x),
#   times = 500L,
#   unit = 'us'   # display in microseconds
# )

解读汇总输出

microbenchmark 会输出一个包含以下列的汇总表:

  • min — 单次运行中的最快耗时
  • lq / mean / median / uq — 下四分位数、均值、中位数、上四分位数
  • max — 单次运行中的最慢耗时
  • neval — 求值次数

请将中位数作为主要比较指标——它不易受偶发的垃圾回收暂停影响,而这些暂停会使最大值和均值变大。

# Example summary output (unit: microseconds):
#
#         expr    min     lq   mean  median    uq    max neval
#         loop 1203.1 1245.3 1301.7  1262.4 1310.1 2100.8   100
#   vectorized    2.1    2.3    2.9     2.4    2.6   18.3   100
#
# => vectorized is ~525x faster at median
cat('Always compare medians, not means, for microbenchmark results
')

对 microbenchmark 对象使用 summary()

对保存的 microbenchmark 结果调用 summary(mb),会返回一个可以通过程序检查的数据框。您也可以在汇总调用中更改 unit。

# library(microbenchmark)
# x <- rnorm(5000)
# mb <- microbenchmark(
#   vapply_abs  = vapply(x, abs, numeric(1)),
#   base_abs    = abs(x),
#   times = 200L
# )
# s <- summary(mb, unit = 'ms')
# print(s[, c('expr', 'min', 'median', 'max')])

使用 autoplot() 进行可视化比较

autoplot(mb) 使用 ggplot2 绘制各表达式耗时分布的小提琴图或箱线图。这样不仅可以直观看到中位数差异,还能看到不同方案之间的变异程度和重叠情况。

# library(microbenchmark)
# library(ggplot2)
#
# x <- 1:50000
# mb <- microbenchmark(
#   loop   = { s <- 0; for (v in x) s <- s + v },
#   vapply = vapply(x, identity, numeric(1)),
#   vec    = sum(x),
#   times  = 100L
# )
# autoplot(mb)  # opens ggplot2 violin chart

比较循环、vapply 和 sapply

一个经典的基准测试是:使用 for 循环、sapply() 或 vapply() 逐元素应用函数。vapply() 的速度比 sapply() 更快,因为它会预分配结果向量。二者都比完全向量化的代码慢。

# library(microbenchmark)
# x <- runif(5000, 1, 100)
#
# mb <- microbenchmark(
#   for_loop = {
#     r <- numeric(length(x))
#     for (i in seq_along(x)) r[i] <- log(x[i])
#   },
#   sapply_log  = sapply(x, log),
#   vapply_log  = vapply(x, log, numeric(1)),
#   vec_log     = log(x),
#   times = 200L, unit = 'us'
# )
# print(mb)

先检查正确性

在进行基准测试之前,请确认所有表达式返回完全相同的结果。更快但不正确的实现没有意义。使用 identical() 或 all.equal() 比较输出。

# x <- runif(1000)
# r1 <- sapply(x, sqrt)
# r2 <- sqrt(x)
# r3 <- vapply(x, sqrt, numeric(1))
#
# stopifnot(isTRUE(all.equal(r1, r2)))
# stopifnot(isTRUE(all.equal(r1, r3)))
# cat('All three produce identical results -- safe to benchmark
')
cat('Always verify correctness before comparing speed
')

使用 setup 参数进行基准测试

使用 setup 参数在计时表达式运行前执行一次代码。如果您测量的不是数据创建过程,这样可以避免将创建数据的时间计入基准测试。

# library(microbenchmark)
#
# microbenchmark(
#   sort_base  = sort(x),
#   sort_order = x[order(x)],
#   setup = { x <- rnorm(10000) },
#   times = 100L
# )
# Each iteration refreshes x via setup, then times sort_base and sort_order

在分析中报告基准测试结果

分享基准测试结果时,请务必报告:

  • R 版本和运行平台
  • 程序包版本
  • 使用的 times 值
  • 参与基准测试的数据规模

不同机器上的耗时不具有可移植性——比较实现时,请报告比值,而不是绝对数值。

cat('R version    :', R.version$version.string, '
')
cat('Platform     :', R.version$platform, '
')
cat('Logical cores:', parallel::detectCores(), '
')

快速检查:microbenchmark 指标

在比较两个实现时,microbenchmark 输出中的哪个汇总统计量最可靠?

microbenchmark 回顾

microbenchmark 是 R 中进行严格微基准测试的标准工具:

  • 传递带名称的表达式,并设置 times 来控制重复次数
  • 使用 unit = 'us' 或 'ms' 获得易读的输出
  • 比较中位数——它们不易受垃圾回收异常值影响
  • 使用 autoplot() 可视化耗时分布
  • 在基准测试前使用 all.equal() 验证正确性
免费开始

用 AI 导师学习 R — 免费

在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。

课程
43
课程
159

常见问题解答

「使用 microbenchmark 进行基准测试」课时是免费的吗?

是的 — 「使用 microbenchmark 进行基准测试」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 R Academy 课程的其余内容,请升级到 CoddyKit PRO。 R Academy 课程共包含 4 节课。

「使用 microbenchmark 进行基准测试」这节课中我会学到什么?

使用 microbenchmark() 对多个实现进行统计比较 你通过在浏览器中直接运行的动手代码来练习 R Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 R Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 R Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「使用 microbenchmark 进行基准测试」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 R Academy 课中编写并运行代码吗?

能。每节 R Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. system.time() 与 proc.time()
  2. 使用 Rprof 和 profvis 分析代码性能
  3. 用向量化提升速度
  4. 使用 microbenchmark 进行基准测试
← 返回 R Academy