为什么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代码的更多相关文章

  1. 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/ ...

  2. 使用记忆化优化你的 R 代码

    目录 使用记忆化优化你的 R 代码 R 中的性能优化 R 何时变慢 R 何时变(更)快 R 中的记忆化 何时使用记忆化 使用记忆化优化你的 R 代码 本文翻译自<Optimize your R ...

  3. A1128 | 逻辑想象能力、简洁高效美观的代码、memset的使用情景

    写了三遍才AC,这真是对智商极大的侮辱 C++代码: #include <stdio.h> #include <memory.h> #include <math.h> ...

  4. 神经网络模型及R代码实现

    神经网络基本原理 一.神经元模型 图中x1~xn是从其他神经元传来的输入信号,wij表示表示从神经元j到神经元i的连接权值,θ表示一个阈值 ( threshold ),或称为偏置( bias ).则神 ...

  5. 建模分析之机器学习算法(附python&R代码)

    0序 随着移动互联和大数据的拓展越发觉得算法以及模型在设计和开发中的重要性.不管是现在接触比较多的安全产品还是大互联网公司经常提到的人工智能产品(甚至人类2045的的智能拐点时代).都基于算法及建模来 ...

  6. 可以编辑R代码的eclipse插件

    说到强大的IDE,eclipse肯定是首先会被想到的几个之一,幸运地是,R也能使用它.在http://www.walware.de/goto/statet上有个StatET的插件,专门为R而做,从此R ...

  7. 编写高效的Android代码

    编写高效的Android代码 毫无疑问,基于Android平台的设备一定是嵌入式设备.现代的手持设备不仅仅是一部电话那么简单,它还是一个小型的手持电脑,但是,即使是最快的最高端的手持设备也远远比不上一 ...

  8. 如何让R代码按计划执行

    应用场景:你编写了R代码,每天对提交的数据进行分析,你希望它你吃饭的时候执行完毕,生成图表. 那么你需要安装taskscheduleR的包. 怎么操作,看帮助呗.

  9. 编写高效的jQuery代码

    http://www.css88.com/jqapi-1.9/ 编写高效的jQuery代码 最近写了很多的js,虽然效果都实现了,但是总感觉自己写的js在性能上还能有很大的提升.本文我计划总结一些网上 ...

随机推荐

  1. IBM x3250m5安装redhat 6.5 加载raid卡驱动

    原文地址:http://www.i5i6.net/post/118.html 1. 下载对应raid卡驱动 for redhat6.5 x64(如本次x3250 m5 c100阵列卡驱动 lsi_dd ...

  2. go 面向对象

    结构体 创建结构体变量和访问结构体字段 package main import "fmt" //创建结构体变量和访问结构体字段 type Person struct { Name ...

  3. 使用 Jest 进行愉快的 JavaScript(TypeScript) 测试

    一般我们不管是做前端还是后端,为了提高代码的质量,会选择一种测试驱动开发(TDD)的办法来写代码进行单元测试.Jest 是 Facebook 团队开发的一款测试框架,为的是提高开发者的"开发 ...

  4. 题解【CF1311F Moving Points】

    \[ \texttt{Preface} \] 赛时,把 " 任意时刻 " 理解成 " 整数时刻 " 了,看起来一脸不可做的亚子,还各种推式子. 话说我为什么觉得 ...

  5. C#设计模式学习笔记:(4)建造者模式

    本笔记摘抄自:https://www.cnblogs.com/PatrickLiu/p/7614630.html,记录一下学习过程以备后续查用. 一.引言 在现实生活中,我们经常会遇到一些构成比较复杂 ...

  6. Linux文件夹被杀死求解?

    Linux中提示cheese.e-calendar-factory 两个文件夹被杀死 程序错误1.cheese process /usr/bin/cheese was killed by signal ...

  7. PHP0008:PHP基础-数组

  8. C# 工具类LogHelper

    一.创建一个WinForm的项目,并通过NuGet安装log4net. 二.创建LogHelper类以及log4net.config配置文件. 三.编写相关代码. 1.LogHelper类 using ...

  9. sql server 发送邮件

    -- BI EMAIL declare @CC varchar(10),@MAIL varchar(500), @str varchar(800),@year varchar(4),@month va ...

  10. 虚拟机NAT模式连接外网

    虚拟机三种联网方式: 一.NAT(推荐使用)                功能:①可以和外部网络连通    ②可以隔离外部网络 二.桥接模式                        功能:直接 ...