【发布时间】:2015-04-05 12:07:43
【问题描述】:
从两位好心人那里得到help后,我设法从数据框+plyr切换到数据表。
情况和我的问题
随着我的工作,我注意到当我使用 := 向我的数据集添加 1 个新列时,峰值内存使用量几乎翻了一番,从 3.5GB 到 6.8GB(根据 Windows 任务管理器)包含约 200K 行乘 2.5K 列。
然后我尝试了 200M 行乘 25 列,增加了从 6GB 到 7.6GB,然后在 gc() 之后下降到 7.25GB。
特别是关于添加新列,Matt Dowle 本人提到here:
使用它的 := 运算符,您可以:
Add columns by reference Modify subsets of existing columns by reference, and by group by reference Delete columns by reference这些操作都不会复制(可能很大)data.table 全部,甚至一次都没有。
问题 1:如果根本不复制 data.table,为什么要为具有 2.5K 列的 DT 添加单列“NAs”加倍使用的峰值内存?
问题2:为什么DT为200M x 25时不会发生翻倍?我没有为此包含打印屏幕,但请随时更改我的代码并尝试。
使用测试代码打印内存使用情况
干净重启,打开 RStudio 和 MS Word - 已使用 103MB
在运行 DT 创建代码之后但在添加列之前 - 使用了 3.5GB
在添加 1 列填充 NA 之后,但在 gc() 之前 - 使用了 6.8GB
运行 gc() 后 - 使用了 3.5GB
测试代码
为了进行调查,我编写了以下与我的数据集非常相似的测试代码:
library(data.table)
set.seed(1)
# Credit: Dirk Eddelbuettel's answer in
# https://stackoverflow.com/questions/14720983/efficiently-generate-a-random-sample-of-times-and-dates-between-two-dates
RandDate <- function(N, st="2000/01/01", et="2014/12/31") {
st <- as.POSIXct(as.Date(st))
et <- as.POSIXct(as.Date(et))
dt <- as.numeric(difftime(et,st,unit="sec"))
ev <- runif(N, 0, dt)
rt <- as.character( strptime(st + ev, "%Y-%m-%d") )
}
# Create Sample data
TotalNoCol <- 2500
TotalCharCol <- 3
TotalDateCol <- 1
TotalIntCol <- 600
TotalNumCol <- TotalNoCol - TotalCharCol - TotalDateCol - TotalIntCol
nrow <- 200000
ColNames = paste0("C", 1:TotalNoCol)
dt <- as.data.table( setNames( c(
replicate( TotalCharCol, sample( state.name, nrow, replace = T ), simplify = F ),
replicate( TotalDateCol, RandDate( nrow ), simplify = F ),
replicate( TotalNumCol, round( runif( nrow, 1, 30 ), 2), simplify = F ),
replicate( TotalIntCol, sample( 1:10, nrow, replace = T ), simplify = F ) ),
ColNames ) )
gc()
# Add New columns, to be run separately
dt[, New_Col := NA ] # Additional col; uses excessive memory?
研究完成
我没有发现太多关于 DT 的内存使用的讨论,有很多列,只有this,但即便如此,它也不是专门关于内存的。
关于大型数据集 + 内存使用的大多数讨论都涉及行数非常大但列相对较少的 DT。
我的系统
Intel i7-4700 4 核/8 线程; 16GB DDR3-12800 内存; Windows 8.1 64 位; 500GB 7200rpm 硬盘; 64 位 R;数据表ver 1.9.4
免责声明
请原谅我使用“非 R”方法(即任务管理器)来测量使用的内存。 R 中的内存测量/分析是我还没有弄清楚的东西。
编辑 1:更新到数据表 1.9.5 版并重新运行后。不幸的是,问题仍然存在。
【问题讨论】:
-
@shadow,我认为您的意思是
tables(),感谢您向我强调此功能-我以前不知道。我浏览了函数描述,它似乎报告了 DT 使用的最终内存,而不是处理期间使用的最大内存(即包括工作内存)。不确定这些数字与任务管理器报告的数字有何关系。如果我错了,请纠正我。 -
仅供参考,
?tables将您带到帮助页面,所以这是故意的。同样,您可以输入?truelength以获取有关 data.tables 如何处理内存的信息。 -
这很可能是由于this bug, #921,它已在
1.9.5中修复。发生了一些不必要的副本(我认为是从1.9.0回归)。我建议在1.9.5上再试一次。 -
嗯,似乎发生了一些复制,而只是从内部函数返回一个值。将尝试找到一个更直接的示例来重现,看看它是否可以修复。谢谢。
-
嗨@Arun,仅供参考,我已经在 Github 上提交了一个问题。希望修复是一个简单的...
标签: r memory data.table large-data