笔记:
一、R输入命令时速度不要太快,终究是个统计软件,不是编程!
二、memory.limit()查看当前操做系统分配内存给R的最大限
度(单位是M?)
三、要常常 rm(object) 或者 rm(list=ls()) 和 gc()释放内存空间
四、尽可能提早设置矩阵大小固定不变,矩阵
每增加一次,即便赋给同名的变量,都须要新开辟一块更大的空间
五、尽可能避免循环语句
六、用矩阵,而不是数据框
七、在大数据集运行前如今子数据集上测试程序
八、将数据保存到R的住内存以外的包:
biglm和speedglm包能以高效的形式实现大型数据的线性模型拟合和广义线性模型拟合
分析bigmemory包生成的矩阵:
- biganalytics包提供k均值聚类、列统计和一个biglm的封装
- bigtabulate提供了table()\split()和tapply()功能
- bigalgebra包提供了高级的线性代数函数
biglar包跟ff配合使用,为在内存中没法放至的大数据提供了最小角回归,lasso和逐步回归分析。
Borbdingnag包能够处理大数字(大于2的1024次方的数)
写R程序的人,相信都会遇到过“cannot allocate vector of size”或者“没法分配大小为...的矢量”这样的错误。缘由很简单,基本都是产生一个大矩阵等对象时发生的,最干脆的解决办法有两种,第一种是加大内存换64位系统,第二种是改变算法避免如此大的对象。第一种办法,是最好的办法,不过大对象的需求是没有止尽的,终究不是长久之道。第二种办法是最好的思路,不管多么大的对象都是能够弄小的,无非就是分而治之、时间换空间等,对算法的研究也是没有止尽的。
升级硬件和改进算法是解决内存问题的永恒的办法,超出了本文想要表述的范围。在这里,只是简单谈谈R语言的内存管理和垃圾清理机制,只有对这些有所了解,才能对任何问题都能找到针对性的解决办法。
相信全部人在遇到没法分配矢量这一问题后,都能很快地找到
改变“--max-mem-size”(假设都是在Windows下)或者“memory.limit
”的方法,的确,这是最直接的方法。由于出现新对象没法分配内存的直接缘由就是内存不够,R获取内存的方式和其余应用程序同样,都是向操做系统要内存,若是没法获取连续的某个大小的内存空间,就会出现没法分配内存的错误。因为你们使用R时一般都是自动安装自动运行,操做系统愿意分配给R多少内存都是采用的默认设置,在R中使用命令memory.size(NA)或者memory.limit()能够看到当前设置下操做系统能分配给R的最大内存是多少。同时能够
使用memory.size(F)查看当前R已使用的内存,memory.size(T)查看已分配的内存
(注意刚开始时已使用内存和已分配内存是同步增长的,可是随着R中的垃圾被清理,已使用内存会减小,而已分配给R的内存通常不会改变。)。若是memory.limit()获得的数是一个很小的内存,说明操做系统过小气了,留那么多内存给别的程序用不给R。解决办法很简单,就是打开R时不经过双击图标,而是在“运行”中输入“Rgui --max-mem-size 2Gb”(假设要分配2G内存且在环境变量中正确设置了R的安装文件夹),在运行memory.limit()就会发现内存加大了,其实更简单的方法是直接在R中运行memory.limit(2000),效果如出一辙,并且不用重启R。
惋惜大多数状况下改变这个值也不会有效果,由于这个值已经足够大,那么没法分配内存的缘由不是操做系统小气对R不公,而是它确实拿不出来,谁找它要也拿不出来。这个时候就须要了解R的内存管理究竟是怎么回事了。
R的操做基本都是经过变量来实现的,变量能够是各类各样的对象类型,R中的对象(好比矩阵)在内存中存于两种不一样的地方,一种是堆内存(heap),其基本单元是“Vcells”,每一个大小为8字节,新来一个对象就会申请一块空间,把值所有存在这里,和C里面的堆内存很像。第二种是地址对(cons cells),和LISP里的cons cells道理同样,主要用来存储地址信息,最小单元通常在32位系统中是28字节、64位系统中是56字节。在R中,能够经过ls()来查看当前全部对象名,对于每个对象,能够经过object.size(x)来查看其占用内存的大小。
若是是由于当前对象占用内存过多,那么能够经过处理对象来获取更大的可用内存。一个颇有用的方法是改变对象的存储模式,经过
storage.mode(x)能够看到某个对象的存储模式
,好比某个矩阵默认就是“double”的,若是这个矩阵的数值都是整数甚至0-1,彻底不必使用double来占用空间,可使用storage.mode(x) <- "integer"将其改成整数型,能够看到该对象的大小会变为原来的一半。
对于当前对象占用内存过多的状况,一个很主要的缘由就是在写程序的过程当中形成了太多的中间对象,R是一个很方便的语言,你们使用它通常都是写各类复杂的模型和算法,不少问题构造几个矩阵通过一系列的矩阵运算就能够很快解决,可是这些辅助算法的大矩阵若是不清理,就会留在系统中占内存。所以在写程序中对于中间对象,常用
rm(x)是一个很好的习惯,若是是很是重要的信息不想删掉,能够存在硬盘里,好比csv文件或者RSqlite等
。
rm()用来删除对象时,只会删除变量的引用,并不会当即清除占用的内存空间,失去引用的对象就成了内存中的垃圾,R清理垃圾的机制和JAVA很像,都是在必定时间内自动发现垃圾再集中清理。因此经过rm()删除对象后在Windows的任务管理器能够看到R进程占用的内存并无被当即释放,而是过一段时间后才会清理。若是想要删除的对象马上被清理,能够运行
垃圾处理函数gc(),将会马上释放空间
。可是一般不是很必要,由于当内存不够时系统会自动清理垃圾的,咱们要作的只是将再也不使用的对象rm()掉,在写R程序时应该养成习惯。
不少时候,在程序中尤为是循环里,若是内存处理不当,还没来得及垃圾清理,就会把内存撑爆,所以新建对象时必定要考虑到R的内存管理机制。你们都知道R中矩阵的维度并不须要赋一个固定的值(不少语言的数组长度不能为变量),这为写程序带来了极大的方便,所以常常在循环中会出现某个矩阵愈来愈长的状况,实际上,
矩阵每增加一次,即便赋给同名的变量,都须要新开辟一块更大的空间
,假设初始矩阵为100K,第二个为101K,一直增到120K,那么,将会分别开辟100K、101K一直到120K的连续堆内存,若是
一开始就开一块120K的,使之从101K逐渐增加到120K,将会大大地节约内存
。cbind函数也是这个道理,因此在循环中要注意不要滥用。
要处理好内存的问题其实很简单,养成随时关注内存的习惯便可,每新建一个对象或者循环赋值的时候适当估算一下所占内存,大内存的中间变量用完后记得清理。若是实在须要新建一个巨大的对象,那么就该考虑一些
专门处理大内存对象以及并行处理的包,好比bigmemory
等