在R语言中释放内存

6
在R中,我正在尝试将几组时间序列数据从http://www.truefx.com/?page=downloads合并并转换为xts格式,但是由于文件很大且有很多文件,这在我的笔记本电脑上引起了问题。它们被存储为已压缩为zip文件的csv文件。
下载和解压它们非常容易(尽管会占用硬盘上很多空间)。
使用data.table包中的新fread()函数将一个月的350MB+文件加载到R中相对直接。
一些datatable的转换是在函数内完成的,以便可以轻松读取时间戳并生成中间列。然后将datatable保存为RData文件到硬盘上,并从工作空间中删除所有对datatable对象的引用,在删除后运行gc()...但是,当查看我的Activity Monitor(从Mac运行)中的R会话时,它仍然占用了近1GB的RAM...而且事情似乎有点滞后...我打算同时加载几年的csv文件,将它们转换为可用的datatables,将它们组合起来,然后创建一个单独的xts对象,如果只有一个月使用1GB的RAM,这似乎是不可行的。
我知道我可以顺序下载每个文件,将其转换,保存并关闭R,重复此过程直到我有一堆RData文件,然后可以加载和绑定它们,但是希望有一种更有效的方法来做到这一点,以便在删除对datatable的所有引用后,您能够恢复到“正常”或启动时的RAM使用水平。有比gc()更好的清除内存的方法吗?任何建议将不胜感激。

1
如果您使用read.csv而不是fread,是否有相同的症状? - GSee
1
似乎与https://dev59.com/fHM_5IYBdhLWcg3wPAdF有关。 - redmode
使用 x <- read.csv(...) 会将内存使用量提高到1.2GB,然后运行 rm(x),接着运行 gc(),只能将其降至894MB...仍远远达不到初始启动/初始化R时约75MB的内存使用量。 - h.l.m
@redmode 我同意它可能与你放链接的那个问题有关,然而,建议运行多次 "gc()" 的解决方案似乎并没有在降低RAM使用量方面帮助很大...... - h.l.m
1个回答

7
在我的项目中,我需要处理许多大文件。我按照以下原则组织了例行程序:
  1. 将占用内存较多的操作隔离在单独的 R 脚本中。
  2. 在新进程中运行每个脚本,在执行后销毁该进程。这样系统就会释放使用的内存。
  3. 通过文本文件向脚本传递参数。
考虑下面的玩具示例。
数据生成:
setwd("/path/to")
write.table(matrix(1:5e7, ncol=10), "temp.csv") # 465.2 Mb file

slave.R - 内存消耗部分

setwd("/path/to")
library(data.table)

# simple processing
f <- function(dt){
  dt <- dt[1:nrow(dt),]
  dt[,new.row:=1]
  return (dt)
}

# reads parameters from file
csv <- read.table("io.csv")
infile  <- as.character(csv[1,1])
outfile <- as.character(csv[2,1])

# memory-hungry operations
dt <- as.data.table(read.csv(infile))
dt <- f(dt)
write.table(dt, outfile)

master.R - 在单独的进程中执行从机


setwd("/path/to")

# 3 files processing
for(i in 1:3){
  # sets iteration-specific parameters
  csv <- c("temp.csv", paste("temp", i, ".csv", sep=""))
  write.table(csv, "io.csv")

  # executes slave process
  system("R -f slave.R")
}

@MatthewDowle:是的,我尝试过fread,发现它非常适合我的需求。但是据我所知,目前CRAN上的data.table没有包含它?因此,我决定在这里放置安全的read.tablewrite.table - redmode
@MatthewDowle:更重要的是,@h.l.m在使用fread时报告了内存问题。因此,这不是我回答的重点。基本思路是在单独的进程中运行占用大量内存的任务,以确保内存得到释放。 - redmode
谢谢@redmode,好棒的解决方案!完美运作!一个很好的小技巧来释放内存!特别是与fread()结合使用时!再次感谢@MatthewDowle的贡献! - h.l.m
据我所知,你无法减小R的全局字符串缓存的大小。它只会增加。这将是一个很好的新问题! - Matt Dowle
@h.l.m 也许你应该让你的示例可重现,并展示一下你在这些中间步骤中所做的事情。 - GSee
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接