笔记:
1、R输入命令时速度不要太快,终究是个统计软件,不是编程!
2、memory.limit()查看当前操作系统分配内存给R的最大限度(单位是M?)
3、要经常 rm(object) 或者 rm(list=ls()) 和 gc()释放内存空间
4、尽量提前设置矩阵大小固定不变,矩阵每增长一次,即使赋给同名的变量,都需要新开辟一块更大的空间
5、尽量避免循环语句
6、用矩阵,而不是数据框
7、在大数据集运行前现在子数据集上测试程序
8、将数据保存到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等


 
除了 Hadoop 以外,似乎 colbycol 包是方案之一:http://colbycol.r-forge.r-project.org/
另,stackoverflow 第七章的範例:http://ishare.edu.sina.com.cn/f/23695419.html

【R笔记】R的内存管理和垃圾清理的更多相关文章

  1. R内存管理与垃圾清理

    1.内存查看 memory.limit():查看内存大小 memory.limit(n):申请内存大小 memory.size(NA):查看内存大小 memory.size(T):查看已分配的内存 m ...

  2. CLR via C#深解笔记七 - 自动内存管理(垃圾回收)

    每个应用程序都要使用这样或者那样的资源,比如文件.内存缓冲区.屏幕空间.网络连接.数据库资源等.事实上,在面向对象的环境中,每个类型都代表可供程序使用的一种资源. 要使用这些资源,必须为代表资源的类型 ...

  3. Java内存管理和垃圾回收

    笔记,深入理解java虚拟机 Java运行时内存区域 程序计数器,线程独占,当前线程所执行的字节码的行号指示器,每个线程需要记录下执行到哪儿了,下次调度的时候可以继续执行,这个区是唯一不会发生oom的 ...

  4. C#内存管理与垃圾回收

    垃圾回收还得从根说起,就像生儿育女一样. 根:根是一个位置,存放一个指针,该指针指向托管堆中的一个对象,或是一个空指针不指向任何对象,即为null.根存在线程栈或托管堆中,大部分的跟都在线程栈上,因为 ...

  5. 使用虚幻引擎中的C++导论(四-内存管理与垃圾回收)(终)

    使用虚幻引擎中的C++导论(四)(终) 第一,这篇是我翻译的虚幻4官网的新手编程教程,原文传送门,有的翻译不太好,但大体意思差不多,请支持我O(∩_∩)O谢谢. 第二,某些细节操作,这篇文章省略了,如 ...

  6. Java之美[从菜鸟到高手演变]之JVM内存管理及垃圾回收

    很多Java面试的时候,都会问到有关Java垃圾回收的问题,提到垃圾回收肯定要涉及到JVM内存管理机制,Java语言的执行效率一直被C.C++程序员所嘲笑,其实,事实就是这样,Java在执行效率方面确 ...

  7. iOS学习笔记之ARC内存管理

    iOS学习笔记之ARC内存管理 写在前面 ARC(Automatic Reference Counting),自动引用计数,是iOS中采用的一种内存管理方式. 指针变量与对象所有权 指针变量暗含了对其 ...

  8. javascript中的内存管理和垃圾回收

    前面的话 不管什么程序语言,内存生命周期基本是一致的:首先,分配需要的内存:然后,使用分配到的内存:最后,释放其内存.而对于第三个步骤,何时释放内存及释放哪些变量的内存,则需要使用垃圾回收机制.本文将 ...

  9. 面试题之C# 内存管理与垃圾回收

    面试题之C# 内存管理与垃圾回收 你说说C# 的内存管理是怎么样的 这句话我记了一个多礼拜了, 自从上次东北师大面试之后, 具体请看<随便扯扯东北师大的面试>. 国庆闲着没事, 就大概了解 ...

随机推荐

  1. jsonArray与jsonObject

    最近两个星期接触最多的就是json和map了. 之前用到的json,就是一个键对应一个值,超级简单的一对一关系.现在用到的json那可以层层嵌套啊,刚开始接触的时候,确实有种崩溃的赶脚,不想去理,取个 ...

  2. oracle与mysql与sqlserver的分页

    假设当前是第PageNo页,每页有PageSize条记录,现在分别用Mysql.Oracle和SQL Server分页查询student表. 1.Mysql的分页查询: 1 SELECT 2 * 3 ...

  3. windows10-seaslog安装笔记

    1.seasLog在windows下的安装 首先,要下载seasLog的dll文件,下载地址:http://pecl.php.net/package/SeasLog  选择对应你的系统和php版本的d ...

  4. Windows下使用批处理实现启动关闭mysql_DOS/BAT

    cls @echo off :设置窗口字体颜色 color 0a :设置窗口标题 TITLE MySQL管理程序 by ThinkVenus call :checkAdmin goto menu :菜 ...

  5. compositionstart 、 compositionend 、 input都存在时的解决办法

    $(function () { var cpLock = true; $('#textbox').off().on({ compositionstart: function () {//中文输入开始 ...

  6. dj定时任务

    参考:http://www.mknight.cn/post/13/ https://blog.csdn.net/sicofield/article/details/50937338 一.INSTALL ...

  7. (转载)常用的Python库

    http://forum.ubuntu.com.cn/viewtopic.php?f=63&t=249573&p=2640959 Tkinter ---- Python默认的图形界面接 ...

  8. aiohttp/asyncio 小例子和解释

    #!/usr/bin/env python # encoding: utf-8 import aiohttp import asyncio import time # 通过async def定义的函数 ...

  9. StringUtils.isEmpty()和StringUtils.isBlank() 区别

    isBlank()判断空的情况包括了isEmpty()的情况,isBlank()不仅判断了 无对象.空对象的情况,而且也判断了无意义的空白字符,比如空格等.

  10. springmvc formatter

    以下,来自于Springmvc指南第二版,第93页. Spring的Formatter是可以将一种类型转为另一种类型. 例如用户输入的date类型可能有多种格式. 下面是才用 registrar方式注 ...