内容简介:《R语言编程指南》
《R语言编程指南》
代码性能
简单看函数运行时间,用 system.time()
函数。
高级点,使用 microbenchmark
包的 microbenchmark()
函数。
例如:
library(microbenchmark) x = rnorm(10000) microbenchmark(x) #> Unit: nanoseconds #> expr min lq mean median uq max neval #> x 30 31 47.6 32 32 1561 100
给出了类似 summary()
函数结果的样子,默认计算100次。
代码性能分析
R提供了内置函数 Rprof()
对代码性能进行分析。
使用方法:调用Rprof()开始分析,运行想分析的代码,然后调用Rprof(NULL)停止分析,最后调用summaryRprof()查看分析结果:
x = rnorm(10000) tmp = tempfile(fileext = ".out") Rprof(tmp) for (i in 1:1000) { cumsum(x) } Rprof(NULL) summaryRprof(tmp) #> $by.self #> self.time self.pct total.time total.pct #> "cumsum" 0.06 100 0.06 100 #> #> $by.total #> total.time total.pct self.time self.pct #> "cumsum" 0.06 100 0.06 100 #> "block_exec" 0.06 100 0.00 0 #> "call_block" 0.06 100 0.00 0 #> "eval.parent" 0.06 100 0.00 0 #> "eval" 0.06 100 0.00 0 #> "evaluate_call" 0.06 100 0.00 0 #> "evaluate::evaluate" 0.06 100 0.00 0 #> "evaluate" 0.06 100 0.00 0 #> "handle" 0.06 100 0.00 0 #> "in_dir" 0.06 100 0.00 0 #> "knitr::knit" 0.06 100 0.00 0 #> "local" 0.06 100 0.00 0 #> "process_file" 0.06 100 0.00 0 #> "process_group.block" 0.06 100 0.00 0 #> "process_group" 0.06 100 0.00 0 #> "rmarkdown::render" 0.06 100 0.00 0 #> "timing_fn" 0.06 100 0.00 0 #> "withCallingHandlers" 0.06 100 0.00 0 #> "withVisible" 0.06 100 0.00 0 #> #> $sample.interval #> [1] 0.02 #> #> $sampling.time #> [1] 0.06
当 Rprof()
设定 line.profiling = TRUE
时,将改为分析代码行,而不是函数,这有利于分析复杂的计算过程。
高级点,使用RStudio提供的 profvis()
,它是一个交互式可视化的工具。
install.packages("profvis")
提供代码性能
cmpfun()
前两点不细讲了。
使用字节码编译器
如果不是R内置的函数,一般通过字节码进行编译后再使用会提升速度,这里说下流程:
#载入包 library(compiler) #调用函数进行编译 # 假设我们写了一个自定义的sum函数 sum_cmp = cmpfun(sum) # 然后再使用sum_cmp函数
使用并行计算
由于不同的操作系统有不同的线程和线程模型的实现,因此某些功能在 Linux 和MacOS系统与Windows系统不同。
我们先创建一个伪任务,以方便进行并行计算:
simulate = function(x) { s = 0 for (i in x){ while(i >= 1){ s = i * (i - 1) i = i - 1 } } s }
system.time(simulate(1:11000)) #> 用户 系统 流逝 #> 7.052 0.023 7.087
在Windows下使用
Windows下需要先创建多个R会话的本地集群:
library(parallel) cl = makeCluster(detectCores())
detectCores()
返回我们计算机有的CPU核数目,然后调用 parLapply()
函数,它是并行版本的 lapply()
函数:
system.time(parLapply(cl, 1:11000, simulate)) #> 用户 系统 流逝 #> 0.008 0.001 4.038
当我们不需要这个集群时,调用 stopCluster()
终止刚才创建的R会话。
注意,当我们使用这种方式进行并行计算时,创建了新的R会话,因此环境里没有用户定义的变量。如果有我们自己的数据,需要提前导入。
使用 clusterExport()
可以将数据导入到集群,使用 clusterEvalQ()
可以在每个集群节点上计算表达式。
或者使用 clusterCall()
和 <<-
在每个节点创建全局变量,而 <-
创建局部变量。
stopCluster() #> Error in defaultCluster(cl): no cluster 'cl' supplied and none is registered
Linux和MacOS使用并行计算
在这两个系统上使用并行计算要比Windows容易的多, mclapply()
可直接将当期R会话分配到多个会话中,保留所有内容,并为每个子会话安排任务,并行运行:
system.time( mclapply(1:1100, simulate, mc.cores = detectCores())) #> 用户 系统 流逝 #> 0.135 0.048 0.073
我们无需导出变量到集群中,因为在每个分配的进程中,它们是可以直接使用的。
我们还可以用非常灵活的方式创建并行作业,例如创建一个生成10个随机数的作业:
job1 = mcparallel(rnorm(10), "job1")
然后调用 mccollect()
函数收集作业结果:
mccollect(job1) #> $`3979` #> [1] -0.0816 0.6930 -0.8022 -1.6354 -1.0508 -0.7526 -1.6807 -1.9063 #> [9] -2.2072 -0.1354
还可以通过编程创建并运行多项作业,例如我们创建8项作业,每个随机休眠一段时间:
jobs = lapply(1:8, function(i){ mcparallel({ t = rbinom(1, 5, 0.6) Sys.sleep(t) t }, paste0("job", i)) }) system.time(res <- mccollect(jobs)) #> 用户 系统 流逝 #> 0.018 0.023 3.921
使用Rcpp
并行计算只有在每次迭代都是独立的情况下才可行,这样最终结果才不会依赖运行顺序,然后并非所有的任务都像这样理想。另一种让算法更快的方式是使用Rcpp( http://www.rcpp.org )。
Rcpp是一个扩展包,它使我们能够利用R和C++的无缝整合来编写C++代码。使用Rcpp可以编写C++代码,并且代码中还可以调用R函数,利用R数据结构的优势。
使用Rcpp,先要使用正确的 工具 链,在Windows系统下使用Rtools,在Linux和MacOS下也需要安装正确的C/C++工具链。
然后我们就安装 Rcpp
包:
install.packages("Rcpp")
先在Rcpp目录下创建一个C++源文件:
#include <Rcpp.h> usingnamespace Rcpp; // [[Rcpp::export]] NumericVector timesTwo (NumericVector x){ return x * 2; }
如果你不熟悉C++语法,可以通过 http://www.learncpp.com 学习最简单的部分。
C++是强类型语言,需要指定函数参数的类型和函数返回的类型。使用[[Rcpp::export]]注释的函数会被Rcpp捕获,当在RStudio中执行一个脚本文件,或者直接使用Rcpp::sourceCpp,这些C++函数将被自动编译并移植到R的工作环境中。
Rcpp::sourceCpp("../../R/Rcpp/rcpp-demo.cpp") #> #> > timesTwo(42) #> [1] 84 timesTwo #> function (x) #> .Call(<pointer: 0x112cb3620>, x)
Rcpp官网: http://www.rcpp.org/
一些相关技术与包:
- OpenMP
- RcppParallel
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- AI就是高性能计算
- 高性能计算Lustre性能优化方案
- 英特尔的物联网战役: 聚焦高性能芯片、边缘计算和计算机视觉
- 使用Python提供高性能计算服务
- 气象高性能计算发展的40年
- 戴尔——做你身边的高性能计算助手
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。