R语言高性能编程,优化(一)
这段时间学习了<R高性能编程>这本书,基于这段时间做的项目实践,总结了一些自己的体会,和大家分享
一、为什么R程序有时候会很慢?
1、计算性能的三个限制条件 cpu ram io 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、尽量向量化运算,避免循环
2、使用内置函数。 R中存在很多低级运算符,虽然这些运算符可以组成更加复杂的运算符或者函数,但是和编译性语言相比性能很差,
但是R提供了很多C++编写的计算包。
比如计算 矩阵每一行的和,一般用apply可以解决问题,但是内置函数 rowSums,性能提升11倍,rowSums是使用C预编译的优化函数
开源社区开发了很多函数优化库供R使用,比如 basic linear algebra subprograms (BLAS) 详见:www.netlib.org.blas
3、预分配内存
为什么要预分配内存呢?主要是因为动态分配内存会拖慢程序的运行速度,每当向量大小发生变化,程序都需要做一些额外的工作
经过测试在一个简单的加法运算中,1000 长度的向量的计算,预分配内存之前为25.373秒,之后为0.577 秒
4、使用简单的数据结构
5、使用更加简单的数据结构
比如 如果可以的话,尽量使用matrix 而不是 dataframe,因为大部分矩阵操作首先要把dataframe强制转换为matrix,才开始计算。
如果数据中存在多种变量类型,不可避免的要使用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 解除已分配内存的保护
五、使用GPU让R运行的更快
这里需要注意的是在计算pearson相关性的时候,GPU是比CPU慢的
1、GPU最大的优势是核心数量巨多,所以最适合数据的并行问题,不适合那些线程之间需要大量同步的任务。
2、GPU的性能主要取决于主内存(RAM)和GPU内存之间的数据传输量,因为RAM和CPU内存之间的连接宽带很低。
优秀的GPU编程应该最小化这种传输
----------好了,截止到这里 我们已经了解了R为什么会慢以及如何衡量R代码的性能的问题;并且突破了CPU 限制,提升R程序性能的技术。
后面会以内存和IO方面作为突破口来优化代码,未完待续.....
原文出处:http://www.cnblogs.com/qiaoyihang/p/7779144.html
R语言高性能编程,优化(一)的更多相关文章
- R语言高性能编程(三)
一.使用并行计算加倍提升性能1.数据并行 VS 任务并行实现数据并行的算法scoket 并行性注意并行计算时间并不与执行任务的计算资源数目成正比(计算机核心),amdahl定律:并行代码的速度受限于串 ...
- R语言高性能编程(二)
接着上一篇 一.减少内存使用的简单方法1.重用对象而不多占用内存 y <- x 是指新变量y指向包含X的那个内存块,只有当y被修改时才会复制到新的内存块,一般来说只要向量没有被其他对象引用,就可 ...
- R语言面向对象编程:S3和R6
一.基于S3的面向对象编程 基于S3的面向对象编程是一种基于泛型函数(generic function)的实现方式. 1.S3函数的创建 S3对象组成:generic(generic FUN)+met ...
- 【转】R语言知识体系概览
摘要:R语言的知识体系并非语法这么简单,如果都不了R的全貌,何谈学好R语言呢.本文将展示介绍R语言的知识体系结构,并告诉读者如何才能高效地学习R语言. 最近遇到很多的程序员都想转行到数据分析,于是就开 ...
- R语言中文社区历史文章整理(类型篇)
R语言中文社区历史文章整理(类型篇) R包: R语言交互式绘制杭州市地图:leafletCN包简介 clickpaste包介绍 igraph包快速上手 jiebaR,从入门到喜欢 Catterpl ...
- Rserve详解,R语言客户端RSclient【转】
R语言服务器程序 Rserve详解 http://blog.fens.me/r-rserve-server/ Rserve的R语言客户端RSclient https://blog.csdn.net/u ...
- 【计理05组01号】R 语言基础入门
R 语言基本数据结构 首先让我们先进入 R 环境下: sudo R 赋值 R 中可以用 = 或者 <- 来进行赋值 ,<- 的快捷键是 alt + - . > a <- c(2 ...
- R语言:用简单的文本处理方法优化我们的读书体验
博客总目录:http://www.cnblogs.com/weibaar/p/4507801.html 前言 延续之前的用R语言读琅琊榜小说,继续讲一下利用R语言做一些简单的文本处理.分词的事情.其实 ...
- R语言编程艺术(5)R语言编程进阶
本文对应<R语言编程艺术> 第14章:性能提升:速度和内存: 第15章:R与其他语言的接口: 第16章:R语言并行计算 ================================== ...
随机推荐
- GCD之死锁
GCD相当好用,但用不好就会死锁,始终要记着这样一句秘籍: 不要在串行队列放dispatch_sync.dispatch_apply 下面看几个例子 1 2 3 4 5 6 7 8 9 10 11 1 ...
- Java笔记—— 类与对象的几个例子
问题1 按要求编写java应用程序: 编写西游记人物类,属性有:身高,名字和武器.方法有:显示名字,显示武器. 在main方法中创建两个对象.猪八戒和孙悟空,并分别为他们的两个属性名字和武器赋值,最后 ...
- 浅析Spring MVC工作机制
1.如何使用Spring MVC? 在web.xml中配置一个DispatcherServlet DispatchServlet初始化的时候会去寻找一个在应用程序的WEB-INF目录下的配置文件,命名 ...
- python文件名和文件路径操作
Readme: 在日常工作中,我们常常涉及到有关文件名和文件路径的操作,在python里的os标准模块为我们提供了文件操作的各类函数,本文将分别介绍"获得当前路径""获得 ...
- 使用 TUN 设备实现一个简单的 UDP 代理隧道
若要实现在 Linux 下的代理程序,方法有很多,比如看着 RFC 1928 来实现一个 socks5 代理并自行设置程序经过 socks5 代理等方式,下文是使用 Linux 提供的 tun/tap ...
- Scaffolding Template on Asp.Net Core Razor Page
Scaffolding Template Intro 我们知道在Asp.Net MVC中,如果你使用的EF的DBContext的话,你可以在vs中通过右键解决方案-添加控制器-添加包含视图的控制器,然 ...
- java一些问题的思考
1.思考 为什么java规定作为程序入口点的main() 方法静态的? 在java中,main()方法是java应用程序的入口方法,也就是说,程序在运行的时候,第一个执行的方法就是main()方法,这 ...
- 【笔记】php常用函数
phpusleep() 函数延迟代码执行若干微秒.unpack() 函数从二进制字符串对数据进行解包.uniqid() 函数基于以微秒计的当前时间,生成一个唯一的 ID.time_sleep_unti ...
- 【JAVA零基础入门系列】Day6 Java字符串
字符串,是我们最常用的类型,每个用双引号来表示的串都是一个字符串.Java中的字符串是一个预定义的类,跟C++ 一样叫String,而不是Char数组.至于什么叫做类,暂时不做过多介绍,在之后的篇章中 ...
- 一道javascript面试题(闭包与函数柯里化)
要求写一个函数add(),分别实现能如下效果: (1)console.log(add(1)(2)(3)(4)()); (2)console.log(add(1,2)(3,4)()); (3)conso ...