前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >R语言之内存管理

R语言之内存管理

作者头像
悟乙己
发布2019-05-28 20:01:04
1.9K0
发布2019-05-28 20:01:04
举报
文章被收录于专栏:素质云笔记素质云笔记

在处理大型数据过程中,R语言的内存管理就显得十分重要,以下介绍几种常用的处理方法。 1,设置软件的内存

代码语言:javascript
复制
<span style="font-size:14px;">memory.size(2048) #设置内存大小
memory.size(NA) #查看当前设置下最大内存(?"Memory-limits")
#or memory.limit()
memory.size(F) #查看当前已使用的内存
#or
library(pryr)
mem_used()

mem_change(x <- 1:1e6) #查看执行命令时内存的变化
memory.size(T)  #查看已分配的内存</span>

注意刚开始时已使用内存和已分配内存是同步增加的,但是随着R中的垃圾被清理,已使用内存会减少,而已分配给R的内存一般不会改变。 2,对象的存储 R中的对象在内存中存于两种不同的地方,一种是堆内存(heap),其基本单元是“Vcells”,每个大小为8字节,新来一个对象就会申请一块空间,把值全部存在这里,和C里面的堆内存很像。第二种是地址对(cons cells),和LISP里的cons cells道理一样,主要用来存储地址信息,最小单元一般在32位系统中是28字节、64位系统中是56字节。

代码语言:javascript
复制
<span style="font-size:14px;">ls()           #查看当前对象
object.size()    查看对象所占内存
#or
library(pryr)
object_size()  #区别于前者,它进行了换算</span>

1)新建对象分配合适的内存

R会将新的对象存储在“连续”的内存中,如果没有这样的空间就会返回“Cannot allocate vector of size...” 的错误,有以下几种处理方法: a) 如果有多个矩阵需要存储,确保优先存储较大的矩阵,然后依次存储较小的矩阵. b) 预先分配合适的内存. 大家都知道R中矩阵的维度并不需要赋一个固定的值(很多语言的数组长度不能为变量),这为写程序带来了极大的方便,因此经常在循环中会出现某个矩阵越来越长的情况,实际上,矩阵每增长一次,即使赋给同名的变量,都需要新开辟一块更大的空间,假设初始矩阵为100K,第二个为101K,一直增到120K,那么,将会分别开辟100K、101K一直到120K的连续堆内存,如果一开始就开一块120K的,使之从101K逐渐增长到120K,将会大大地节约内存。cbind函数也是这个道理,所以在循环中要注意不要滥用。 c) 换到64位的计算机,这种问题较少出现. 2)改变当前对象的存储模式 例如某个矩阵默认就是"double"的,如果这个矩阵的数值都是整数甚至0-1,完全没必要使用double来占用空间,可以将其改为整数型,可以看到该对象的大小会变为原来的一半。

代码语言:javascript
复制
<span style="font-size:14px;">storage.mode(x)    #查看对象的存储模式
storage.mode(x) <- "integer"  #整数型存储模式</span>

3)清理中间对象

代码语言:javascript
复制
<span style="font-size:14px;">rm() #删除变量的引用,经常用它来清理中间对象,其中比较重要的文件可以存在硬盘里,比如csv文件或者RSqlite等
gc() #清理内存空间</span>

4)清理其他对象 .ls.objects() #查看内存消耗较大的文件,并处理掉其他无关对象.代码如下:

代码语言:javascript
复制
<span style="font-size:14px;">.ls.objects <- function (pos = 1, pattern, order.by = "Size", decreasing=TRUE, head = TRUE, n = 10) {
  napply <- function(names, fn) sapply(names, function(x)
          fn(get(x, pos = pos)))
  names <- ls(pos = pos, pattern = pattern)
  obj.class <- napply(names, function(x) as.character(class(x))[1])
  obj.mode <- napply(names, mode)
  obj.type <- ifelse(is.na(obj.class), obj.mode, obj.class)
  obj.size <- napply(names, object.size) / 10^6 # megabytes
  obj.dim <- t(napply(names, function(x)
            as.numeric(dim(x))[1:2]))
  vec <- is.na(obj.dim)[, 1] & (obj.type != "function")
  obj.dim[vec, 1] <- napply(names, length)[vec]
  out <- data.frame(obj.type, obj.size, obj.dim)
  names(out) <- c("Type", "Size", "Rows", "Columns")
  out <- out[order(out[[order.by]], decreasing=decreasing), ]
  if (head)
    out <- head(out, n)
  out
}</span>

3,修改存储地址 这部分可参考文献1。在xp系统上试了一下,得到的存储地址总是不变,不知道xp系统上有没有效... 4,选取数据集的子集 这是没有办法的办法,迟早要处理全部的数据,不过可以借此调试代码或是建模,如在合适的地方清理中间对象 5,写成脚本文件 Hadley Wickham 建议写成脚本文件,运行后再清理掉临时文件 6,使用SOAR包 它可以将特定对象存储为RData文件并无需加载到内存就能进行分析

代码语言:javascript
复制
<span style="font-size:14px;">r = data.frame(a=rnorm(10,2,.5),b=rnorm(10,3,.5))
library(SOAR)
Sys.setenv(R_LOCAL_CACHE=”testsession”)
ls()
Store(r)
ls()
mean(r[,1])
r$c = rnorm(10,4,.5)
ls()</span>

7,一个有趣的函数 它会告诉你哪一行的代码消耗了多少时间、内存,释放多少内存,复制了多少向量.

代码语言:javascript
复制
<span style="font-size:14px;">library(devtools)
devtools::install_github("hadley/lineprof")
library(lineprof)
source("D:/myprojects/project1/read-delim.R")
prof <- lineprof(read_delim("D:/myprojects/project1/diamonds.csv"))
shine(prof)</span>
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2014年11月14日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档