使用 microbenchmark 进行基准测试
使用 microbenchmark() 对多个实现进行统计比较
使用 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 反馈 — 无需本地设置。
此课程中的所有课时
- system.time() 与 proc.time()
- 使用 Rprof 和 profvis 分析代码性能
- 用向量化提升速度
- 使用 microbenchmark 进行基准测试