在 R 中测量函数执行时间
Posted
技术标签:
【中文标题】在 R 中测量函数执行时间【英文标题】:Measuring function execution time in R 【发布时间】:2011-06-07 07:55:52 【问题描述】:R中是否有衡量函数执行时间的标准化方法?
显然我可以在执行之前和之后取system.time
然后取它们的差异,但我想知道是否有一些标准化的方式或功能(不想发明***)。
我似乎记得我曾经使用过类似以下的东西:
somesysfunction("myfunction(with,arguments)")
> Start time : 2001-01-01 00:00:00 # output of somesysfunction
> "Result" "of" "myfunction" # output of myfunction
> End time : 2001-01-01 00:00:10 # output of somesysfunction
> Total Execution time : 10 seconds # output of somesysfunction
【问题讨论】:
我想你已经想到了proc.time
,因为 system.time
是你需要的。
对于更大的功能,Rprof
很好。它提供了代码块/函数中所有进程的概要文件。
新 R 用户通过 google 找到这个问题:require(microbenchmark)
现在(从几年前开始)是社区标准的计时方式。 times <- microbenchmark( lm(y~x), glm(y~x), times=1e3); example(microbenchmark)
。这会对lm
与glm
进行超过1000 次尝试的统计比较,而不是system.time
仅测试一次。
使用res <- microbenchmark(your code1,your code2)
然后print(res)
查看表格或ggplot2::autoplot(res)
查看箱线图! ref
【参考方案1】:
另一种可能的方法是使用 Sys.time():
start.time <- Sys.time()
...Relevent codes...
end.time <- Sys.time()
time.taken <- end.time - start.time
time.taken
与上面的答案相比,这不是最优雅的方式,但绝对是一种方式。
【讨论】:
这更节省内存,然后是 system.time(),它有效地复制了它的参数。当您处理的数据几乎不适合您的 RAM 时,这一点很重要。 对于使用Sys.time
的人,请阅读以下内容以了解一些警告:Timing R code with Sys.time()
system.time()
对我来说更快。我认为应该接受system.time()
的答案!
这是我了解在多个内核上并行完成长时间计算所需时间的首选方法。在这种情况下,通过此调用测量的挂钟时间足够准确,因为计算机将比执行其他任何操作更忙于计算所有内核,并且计算需要几分钟或几小时才能完成。这是一个非常具体的用例,但值得一提。
对于那些喜欢单线的人:s=Sys.time(); <code here> ; Sys.time()-s;
。这将打印时差以及您的代码可能产生的任何输出。【参考方案2】:
内置函数system.time()
会做到这一点。
像这样使用:system.time(result <- myfunction(with, arguments))
【讨论】:
重要的是要知道system.time()
有一个参数gcFirst
,默认情况下是TRUE
。一方面,这使测量更具可重复性,但可能会产生显着的总运行时间开销(当然,这是未测量的)。
这是用什么单位测量的?例如,我刚刚运行 system.time(result <- myfunction(with, arguments))
并得到 187.564 作为输出 - 是在几秒钟内还是什么?
对于使用system.time
的人,请阅读以下内容以了解一些警告:“object not found” and “unexpected symbol” errors when timing R code with system.time()。
@zsad512 我有理由确定那些是seconds。【参考方案3】:
正如安德烈所说,system.time()
工作正常。对于简短的函数,我更喜欢将replicate()
放入其中:
system.time( replicate(10000, myfunction(with,arguments) ) )
【讨论】:
你最好使用 microbenchmark 包,因为它不包括计时复制的开销。【参考方案4】:microbenchmark
是一个轻量级 (~50kB) 包,或多或少是 R 中用于对多个表达式和函数进行基准测试的标准方法:
microbenchmark(myfunction(with,arguments))
例如:
> microbenchmark::microbenchmark(log10(5), log(5)/log(10), times = 10000)
Unit: nanoseconds
expr min lq mean median uq max neval cld
log10(5) 0 0 25.5738 0 1 10265 10000 a
log(5)/log(10) 0 0 28.1838 0 1 10265 10000
这两个表达式都被评估了 10000 次,平均执行时间约为 25-30 ns。
【讨论】:
【参考方案5】:测量执行时间的更好方法是使用rbenchmark 包。这个包(很容易)允许您指定复制测试的次数以及相对基准应该是多少次。
另请参阅stats.stackexchange 上的相关问题
【讨论】:
Microbenchmark 更好,因为它使用了更高精度的计时函数。 @hadley 但是 rbenchmark 在比较的情况下更加用户友好。对我来说,微基准是升级的 system.time。 rmicrobenchmark 是我们需要的 :) microbenchmark 的维护者反应灵敏 - 我敢打赌他会添加你需要的任何东西。【参考方案6】:还有proc.time()
您可以使用与Sys.time
相同的方式,但它会为您提供与system.time
相似的结果。
ptm <- proc.time()
#your function here
proc.time() - ptm
使用的主要区别
system.time( #your function here )
proc.time()
方法是否仍然执行您的功能,而不仅仅是测量时间...
顺便说一句,我喜欢在 里面使用
system.time
,这样你就可以放一组东西......
【讨论】:
【参考方案7】:“tictoc”包为您提供了一种非常简单的测量执行时间的方法。文档位于:https://cran.fhcrc.org/web/packages/tictoc/tictoc.pdf。
install.packages("tictoc")
require(tictoc)
tic()
rnorm(1000,0,1)
toc()
要将经过的时间保存到变量中,您可以这样做:
install.packages("tictoc")
require(tictoc)
tic()
rnorm(1000,0,1)
exectime <- toc()
exectime <- exectime$toc - exectime$tic
【讨论】:
【参考方案8】:虽然其他解决方案对单个函数有用,但我推荐以下更通用和有效的代码:
Rprof(tf <- "log.log", memory.profiling = TRUE)
# the code you want to profile must be in between
Rprof (NULL) ; print(summaryRprof(tf))
【讨论】:
直到现在我才知道 Rprof,它确实很棒!加上它带有基本 R,所以不需要像microbenchmark
或 profvis
这样的额外包。
我想知道 rprof 是否也可以可视化,例如,如果我们想为它分析的每个项目绘制时间?
@ZawirAmin 有办法,用Rstudio >> profile menu【参考方案9】:
另一个简单但非常强大的方法是使用包profvis
。它不仅测量代码的执行时间,还让您深入了解您执行的每个函数。它也可以用于 Shiny。
library(profvis)
profvis(
#your code here
)
点击here查看一些示例。
【讨论】:
【参考方案10】:如果您愿意,可以使用 MATLAB 风格的 tic
-toc
函数。请参阅其他 SO 问题
Stopwatch function in R
【讨论】:
正要添加proc.time()
……我更喜欢这个可爱的名字。 =)【参考方案11】:
您可以使用Sys.time()
。但是,当您在表格或 csv 文件中记录时差时,您不能简单地说end - start
。相反,您应该定义单位:
f_name <- function (args*)
start <- Sys.time()
""" You codes here """
end <- Sys.time()
total_time <- as.numeric (end - start, units = "mins") # or secs ...
然后你可以使用total_time
,它的格式是正确的。
【讨论】:
【参考方案12】:从上面所有的答案中编译,我想出了使用这些简化的 tic toc 函数
tic <- function() start.time <<- Sys.time()
toc <- function() round(Sys.time() - start.time)
用作:
tic()
Sys.sleep(3)
toc()
以及打印的内容:
时差3秒
【讨论】:
【参考方案13】:基于bench package website:
始终使用可用于每个操作系统的最高精度 API(通常为纳秒级)。 跟踪每个表达式的内存分配。 跟踪每次表达式迭代的 R 垃圾回收的数量和类型。 默认验证表达式结果的相等性,以避免意外地对不等价的代码进行基准测试。 拥有
bench::mark()
from packagebench
用于对一个或一系列表达式进行基准测试,我们认为它比替代方案具有许多优势。bench::press()
,可让您轻松执行和组合大型值网格的基准测试。 默认使用自适应停止,将每个表达式运行一段时间而不是特定次数的迭代。 表达式分批运行,并在使用垃圾收集过滤掉迭代后计算汇总统计信息。这使您可以隔离垃圾收集的性能和对运行时间的影响(有关更多详细信息,请参阅 Neal 2014)。时间和内存使用作为自定义对象返回,这些对象具有人类可读的显示格式(例如 104ns)和比较(例如 x$mem_alloc > "10MB")。
还完全支持使用 ggplot2 进行绘图,包括自定义比例和格式。
用途:
bench::mark(log10(5))
#> # A tibble: 1 × 6
#> expression min median `itr/sec` mem_alloc `gc/sec`
#> <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl>
#> 1 log10(5) 212ns 274ns 2334086. 0B 0
由reprex package (v2.0.1) 于 2021-08-18 创建
【讨论】:
【参考方案14】:几个答案提到取两个Sys.time()
s 的差异,即。
start <- Sys.time()
## ... code here ... ##
end <- Sys.time()
end - start
这会以人类可读的格式打印结果,例如“2 秒的时间差”。但是,由于单位可以变化(从“秒”到“分钟”再到“天”),例如,如果它们的单位不同,则用此方法比较多个运行时的用处不大。
对于非交互式目的,最好指定时间单位。
具体来说,Sys.time()
返回一个POSIXct
对象。取两个POSIXct
s 的差,得到一个difftime
类的对象,它有一个“单位”属性。特别是`-`
操作被定义为在与POSIXct
一起使用时使用difftime()
。也就是说,
time2 - time1
等价于
difftime(time2, time1)
要指定单位属性,请添加units=
参数,例如。
difftime(time2, time1, units="secs")
总而言之,可以使用Sys.time()
测量具有指定单位(秒、分钟等)的运行时间,即。
start <- Sys.time()
## ... code here ... ##
end <- Sys.time()
difftime(end, start, units="secs")
【讨论】:
以上是关于在 R 中测量函数执行时间的主要内容,如果未能解决你的问题,请参考以下文章