高效完成R代码
为什么R有时候运行慢?
参考https://www.cnblogs.com/qiaoyihang/p/7779144.html
一、为什么R程序有时候会很慢?
1、计算性能的三个限制条件 cpu ram io R代码本身(个人觉得能控制的是R代码书写的高效
2、R是运行时解释的 在运行时解释并执行R代码
3、R是单线程的 CPU的强大核心并没卵用,R只会只用一个
4、R需要将全部数据加载到内存 处理的最大数据了取决于内存的限制
这里 linux相比于windows有一个优势,当我们试图装载一个可用内存大小的数据集
数据可能会成功装载,不过一旦可用内存耗尽,操作系统会将内存中的数据换到磁盘(交换空间)上
的交换文件,R人为数据全部装载入内存时间上OS正在做内存和磁盘文件的数据交换工作,如此一来,磁盘IO瓶颈对R性能就有着巨大的影响
5、算法设计影响时间和空间复杂度
时间复杂度:运行R程序需要的计算时间和数据规模之间的关系
空间复杂度:运行R程序需要的内存量和数据规模之间的关系
二、衡量代码的性能常用办法
使用system.time() benchmark() microbenchmark()
Rprof() 的工作原理是在运行R表达式的时候 ,观察R的调用栈,并以固定的时间,默认是0.02秒,对调用栈进行快照
,从而确定函数当前正在执行什么操作。通过这些快照,summaryRprof 能够计算每个函数的耗时
要理解R程序各个部分的性能,快速发现瓶颈,Rprof 是个很有用的工具
内存分析 memory.profiling=TRUE 这个指标会有误导,会偏高,因为有些函数内存尚未释放,
三、加快R运行的简单方法
1、尽量向量化运算,避免循环(这个一定要注意,我稀罕循环,然后容易die)
2、使用内置函数。 R中存在很多低级运算符,虽然这些运算符可以组成更加复杂的运算符或者函数,但是和编译性语言相比性能很差,
但是R提供了很多C++编写的计算包。(大量的内置函数可以使用,所以不需要像python一样)百度一下都能解决内置函数问题。。
比如计算 矩阵每一行的和,一般用apply可以解决问题,但是内置函数 rowSums,性能提升11倍,rowSums是使用C预编译的优化函数
开源社区开发了很多函数优化库供R使用,比如 basic linear algebra subprograms (BLAS) 详见:www.netlib.org.blas
给个demo好了
> # Define the previous solution
> app <- function(x) {
apply(x, 1, sum)
}
>
> # Define the new solution
> r_sum <- function(x) {
rowSums(x)
}
>
> # Compare the methods
> microbenchmark(
app_sol = app(rolls),
r_sum_sol = r_sum(rolls)
)
Unit: microseconds
expr min lq mean median uq max neval
app_sol 27.482 28.434 50.85846 29.0660 30.6125 2004.209 100
r_sum_sol 6.709 7.673 27.95393 8.3015 8.7205 1956.351 100
实行的函数功能一样,从运行时间上来看 rowSums()效率更高
3、预分配内存
上回跑了一个pmg模型,我的电脑崩了。。。事先没有进行预估计
为什么要预分配内存呢?主要是因为动态分配内存会拖慢程序的运行速度,每当向量大小发生变化,程序都需要做一些额外的工作
经过测试在一个简单的加法运算中,1000 长度的向量的计算,预分配内存之前为25.373秒,之后为0.577 秒
4、使用简单的数据结构
5、使用更加简单的数据结构
比如 如果可以的话,尽量使用matrix 而不是 dataframe,因为大部分矩阵操作首先要把dataframe强制转换为matrix,才开始计算。额好吧,其实我都是用dataframe的。
mat是一个矩阵,df是一个数据框,比较一下二者的运行速度
> # Which is faster, mat[, 1] or df[, 1]?
> microbenchmark(mat[, 1], df[, 1])
Unit: microseconds
expr min lq mean median uq max neval
mat[, 1] 2.318 2.701 3.21188 2.9760 3.3265 18.359 100
df[, 1] 11.646 13.010 16.67619 13.8965 15.1355 95.352 100
如果数据中存在多种变量类型,不可避免的要使用dataframe的时候,尽量用subset 和 which 筛选子集后再做运算。
6、使用哈希表进行大型数据上的频繁查找
一个包含N个元素的列表上的查找操作的时间复杂度是O(N) 列表越靠后,查找时间越长,随着N的增加,情况越严重。
CRAN 上可用的R 包是hash, 哈希表上查找操作的时间复杂度为O(1)
7、去CRAN上寻找更快的包
例如:fastcluster,princomp,fastmatch,RcppEigen,data.table,dplyr
四、使用编译代码加快运行速度
1、在运行之前编译R代码 因为每次运行前都需要解析和评估代码。这需要话费大量CPU时间,拖慢运行速度。
利用compiler 包,能在一定程度上减少此问题,提前预编译。
cmpfun 编译函数
compile 编译表达式
cmpfile 编译存储在文件中的R表达式
2、即时编译 激活JIT(just in time) compiler 包的enableJIT
3、在R中使用编译语言 在R中嵌入C、C++、OC、OC++(inline包)
4、调用外部编译代码 Rcpp rJava
5、使用编译代码的注意事项
6、创建R对象及垃圾回收
预分配变量内存,PROTECT防止R的垃圾收集器清理对象。 UNPROTECT 解除已分配内存的保护
7、One thing to note is that && only works on single logical values, i.e., logical vectors of length 1 (like you would pass into an if condition), but & also works on vectors of length greater than 1.
从运行时间上面来看确实是&更快一些
> # Example data
> is_double
[1] FALSE TRUE TRUE
>
> # Define the previous solution
> move <- function(is_double) {
if (is_double[1] & is_double[2] & is_double[3]) {
current <- 11 # Go To Jail
}
}
>
> # Define the improved solution
> improved_move <- function(is_double) {
if (is_double[1] && is_double[2] && is_double[3]) {
current <- 11 # Go To Jail
}
}
>
> # microbenchmark both solutions
> # Very occassionally the improved solution is actually a little slower
> # This is just random chance
> microbenchmark(move, improved_move, times = 1e5)
Unit: nanoseconds
expr min lq mean median uq max neval
move 42 52 107.7818 133 141 110084 1e+05
improved_move 39 50 104.0745 130 138 41764 1e+05
五、使用GPU让R运行的更快
这里需要注意的是在计算pearson相关性的时候,GPU是比CPU慢的
1、GPU最大的优势是核心数量巨多,所以最适合数据的并行问题,不适合那些线程之间需要大量同步的任务。
2、GPU的性能主要取决于主内存(RAM)和GPU内存之间的数据传输量,因为RAM和CPU内存之间的连接宽带很低。
优秀的GPU编程应该最小化这种传输
1.查看R 当前的版本
主要是查看配置信息把
# Print the R version details using version
> version
_
platform x86_64-pc-linux-gnu
arch x86_64
os linux-gnu
system x86_64, linux-gnu
status
major 3
minor 4.4
year 2018
month 03
day 15
svn rev 74408
language R
version.string R version 3.4.4 (2018-03-15)
nickname Someone to Lean On
>
> # Assign the variable major to the major component
> major <- version$major
>
> # Assign the variable minor to the minor component
> minor <- version$minor
2.读入数据更高效
Comparing read times of CSV and RDS files
One of the most common tasks we perform is reading in data from CSV files. However, for large CSV files this can be slow. One neat trick is to read in the data and save as an R binary file (rds) using saveRDS(). To read in the rds file, we use readRDS().
Note: Since rds is R's native format for storing single objects, you have not introduced any third-party dependencies that may change in the future.
To benchmark the two approaches, you can use system.time(). This function returns the time taken to evaluate any R expression. For example, to time how long it takes to calculate the square root of the numbers from one to ten million, you would write the following:
> # How long does it take to read movies from CSV?
> system.time(read.csv("movies.csv"))
user system elapsed
0.395 0.000 0.395
>
> # How long does it take to read movies from RDS?
> system.time(readRDS("movies.rds"))
user system elapsed
0.042 0.000 0.042
不难看出,rds是更高效的,因为数据是加载到R里面的,比外部导入里面之后加载肯定要节省时间。。(或许这么解释不对,但是真的节省时间)
3.辨析 <-和=
这两个是不一样的
Using the <- operator inside a function call will create a new (or overwrite an existing) object.
<-创建的变量的作用范围可以在整个顶层环境,而=仅仅在一个局部环境。(应该是global和局部的关系)https://www.cnblogs.com/xuanlvshu/p/5493222.html
但要<-创建的变量如果是在函数实参传递的时候创建的,其的作用范围可以在整个顶层环境,有一个前提条件:对应的形参在函数内部被用到了。
4.microbenchmark
> # Load the microbenchmark package
> library(microbenchmark)
>
> # Compare the two functions
> compare <- microbenchmark(read.csv("movies.csv"),
readRDS("movies.csv"),
times = 10)
>
> # Print compare
> compare
Unit: nanoseconds
expr min lq mean median uq max neval
read.csv 145 148 414.4 150 158 2741 10
readRDS 110 114 173.1 116 124 681 10
The benchmarkme package provides a set of benchmarks to help quantify your system. More importantly, it allows you to compare your timings with other systems.
> # Load the benchmarkme package
> library( benchmarkme)
>
> # Assign the variable ram to the amount of RAM on this machine
> ram <- get_ram()
> ram
16.3 GB
>
> # Assign the variable cpu to the cpu specs
> cpu <- get_cpu()
> cpu
$vendor_id
[1] "GenuineIntel"
$model_name
[1] "Intel(R) Xeon(R) Platinum 8175M CPU @ 2.50GHz"
$no_of_cores
[1] 4
get_ram():Attempt to extract the amount of RAM on the current machine.
get_cpu():Attempt to extract the CPU model on the current host
pre_allocate():测试边;变量声明的时间的
The growing() function defined below generates n random standard normal numbers, but grows the size of the vector each time an element is added!
向量化代码有多重要?
profvis:Profvis is a tool for visualizing code profiling data from R. It creates a web page which provides a graphical interface for exploring the data. Live demo.

比如这个是可以在网页上面看到的
How many cores does this machine have?
The parallel package has a function detectCores() that determines the number of cores in a machine.
How many cores does this machine have?
一个改写sapply和parSapply的例子
> # Set the number of games to play
> no_of_games <- 1e5
>
> ## Time serial version
> system.time(serial <- sapply(1:no_of_games, function(i) play()))
user system elapsed
7.003 0.005 7.018
>
> ## Set up cluster
> cl <- makeCluster(4)
> clusterExport(cl, "play")
>
> ## Time parallel version
> system.time(par <- parSapply(cl, 1:no_of_games, function(i) play()))
user system elapsed
0.063 0.004 3.168
>
> ## Stop cluster
> stopCluster(cl)
高效完成R代码的更多相关文章
- C#7.2——编写安全高效的C#代码 c# 中模拟一个模式匹配及匹配值抽取 走进 LINQ 的世界 移除Excel工作表密码保护小工具含C#源代码 腾讯QQ会员中心g_tk32算法【C#版】
C#7.2——编写安全高效的C#代码 2018-11-07 18:59 by 沉睡的木木夕, 123 阅读, 0 评论, 收藏, 编辑 原文地址:https://docs.microsoft.com/ ...
- 使用记忆化优化你的 R 代码
目录 使用记忆化优化你的 R 代码 R 中的性能优化 R 何时变慢 R 何时变(更)快 R 中的记忆化 何时使用记忆化 使用记忆化优化你的 R 代码 本文翻译自<Optimize your R ...
- A1128 | 逻辑想象能力、简洁高效美观的代码、memset的使用情景
写了三遍才AC,这真是对智商极大的侮辱 C++代码: #include <stdio.h> #include <memory.h> #include <math.h> ...
- 神经网络模型及R代码实现
神经网络基本原理 一.神经元模型 图中x1~xn是从其他神经元传来的输入信号,wij表示表示从神经元j到神经元i的连接权值,θ表示一个阈值 ( threshold ),或称为偏置( bias ).则神 ...
- 建模分析之机器学习算法(附python&R代码)
0序 随着移动互联和大数据的拓展越发觉得算法以及模型在设计和开发中的重要性.不管是现在接触比较多的安全产品还是大互联网公司经常提到的人工智能产品(甚至人类2045的的智能拐点时代).都基于算法及建模来 ...
- 可以编辑R代码的eclipse插件
说到强大的IDE,eclipse肯定是首先会被想到的几个之一,幸运地是,R也能使用它.在http://www.walware.de/goto/statet上有个StatET的插件,专门为R而做,从此R ...
- 编写高效的Android代码
编写高效的Android代码 毫无疑问,基于Android平台的设备一定是嵌入式设备.现代的手持设备不仅仅是一部电话那么简单,它还是一个小型的手持电脑,但是,即使是最快的最高端的手持设备也远远比不上一 ...
- 如何让R代码按计划执行
应用场景:你编写了R代码,每天对提交的数据进行分析,你希望它你吃饭的时候执行完毕,生成图表. 那么你需要安装taskscheduleR的包. 怎么操作,看帮助呗.
- 编写高效的jQuery代码
http://www.css88.com/jqapi-1.9/ 编写高效的jQuery代码 最近写了很多的js,虽然效果都实现了,但是总感觉自己写的js在性能上还能有很大的提升.本文我计划总结一些网上 ...
随机推荐
- Linux的crontab 命令
crontab 命令 简介 从输入设备读取指令,并将其存放于 crontab 文件中,以供之后读取和执行,即:crontab 是 Linux 系统中添加计划任务,定时执行一些必要的脚本所必不可少的工具 ...
- kettle文本文件写入数据库,简单进行数据清洗
使用kettle7.0,java8.0,Navicat,实验数据使用全国肺炎2月24日的数据 1.建立关系 2.创建连接 如果是第一次连接,可能会出现连接不上的情况,这时候可能情况是没有将Mysql的 ...
- 41.Python中加载静态文件
在一个网页中,不仅仅只有一个html骨架,还需要css样式文件,js执行文件以及一些图片等.因此在DTL中加载静态文件时一个必须要解决的问题.在DTL中,使用static标签来加载静态文件.要使用st ...
- 新年上新!极光认证 Web SDK 首版上线
新年伊始,极光开发者服务也抢先为各位开发者朋友带来了"新年大礼包",几款明星产品都悉数有不少更新: 极光认证 Web SDK 版本上线 相信不少小伙伴早已熟知极光认证这款产品,3秒 ...
- XmlDocument vs XElement
var xmlstr = @"<xml> <AppId>some_appid</AppId> <CreateTime>1413192605&l ...
- CSS背景说明及连写
一.CSS背景说明 CSS 可以添加背景颜色和背景图片,以及来进行图片设置. 1.1 背景图片(image) background-image 属性允许指定一个图片展示在背景中(只有CSS3才可以多背 ...
- CSS 如何实现当鼠标放在上面时整行变色呢?
摘要:下文讲述css中实现鼠标放在指定行上面时,整行变色的方法分享,如下所示: 实现思路:使用:hover伪类,实现当鼠标指向时,其背景色发生相应的变化,如下例所示: 例: 下文中的div,当鼠标放上 ...
- 又一种获取redis cluster slots分布的小脚本
需要:昨晚学习了cluster slots命令,之前写的脚本,有可以换种方法获取到redis cluster slots 分布情况. cluster slots的结果如下: 4 5460 5.5.5. ...
- MySQL8服务无法正常启动的解决方法(1053错误)
个人博客 地址:https://www.wenhaofan.com/article/20190530120545 错误描述 在MySQL安装的最后一步启动失败,如下图所示 在服务和应用程序->服 ...
- MySQL int(1) 与 int(3) 的区别
1.占用的字节都一样,只是容纳字符个数有区别. int(1): 一个字符. int(3): 三个字符. 2.另外要注意的是,无符号整数,自动左侧0填充宽度. int(3),插入值5,会变成005存储. ...