笔记:
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. egrep对于conf文件中去掉#注释,排除无用项

    [root@localhost conf]# egrep -v "#|^$" nginx.conf.default > nginx.conf dd

  2. hive对有特殊值null的数据倾斜处理

    对有特殊值的数据倾斜处理 SET mapred.reduce.tasks=20;SET hive.map.aggr=TRUE;SET hive.groupby.skewindata=TRUE;SET ...

  3. 【POJ 1719】 Shooting Contest (二分图匹配)

    题目链接 把每一列能射的两行和这一列连边,然后跑一边匈牙利就行了. #include <cstdio> #include <cstring> #include <algo ...

  4. Pycharm中快捷键大全

    #1.按住ctrl然后鼠标放在函数上就会提示出这个函数有那些参数,双击进入该函数. 1.Pycharm中快捷键大全,遇到一个更新一个 撤销与反撤销:Ctrl + z,Ctrl + Shift + z ...

  5. ubuntu16.04搭建个人简易DLP

    前言 最近一朋友让我帮忙搭建一台服务器,用做公司的服务器,但是该服务器需要满足一些安全要求,于是乎就有了下面的解决过程^_^ 需求 期望普通用户和管理员都能ssh登陆服务器,但禁止scp或者其他方式下 ...

  6. 转 appium解决每次运行都需要安装Unlock以及AppiumSetting的问题

    一.需要解决的问题 在部分android机型上每次运行最新版的appium-desktop都需要安装AppiumSetting以及Unlock,并且安装过程需要用户手动来确认,即使测试机上已经安装了这 ...

  7. 非旋转Treap——普通平衡树

    扔板跑…… #include<bits/stdc++.h> #define N 100010 #define mp make_pair using namespace std; typed ...

  8. C#实例:Unity依赖注入使用

    http://jingyan.baidu.com/article/c74d6000840b260f6b595d78.html

  9. 在Servlet中获取Spring注解的bean

    最近由于项目中出现了Servlet调用Spring的bean,由于整个项目中所有的bean均是注解方式完成,如@Service,@Repository,@Resource等,但是Spring的容器管理 ...

  10. linux中直接进行系统调用和通过C库调用的示例

    深入了解LINUX,这方面内容不可少,这段时间再补补.. #include <syscall.h> #include <unistd.h> #include <stdio ...