如何使用R

时间:2019-05-31 22:33:24

标签: r memory agent-based-modeling

我正在用R构建基于代理的模型,但是尝试使用大对象却遇到了内存问题。特别是,在初始化时间创建了8个3D阵列,并且在每个时间步长,每个3D阵列都由不同的功能填充。

目前,反导系统运行了1825天,模拟了2500个人在整个地形上移动。风景中有1000个单元格。使用此配置,我不会出现内存问题。

在初始化时,

  • 1个3D阵列就像:

    h <- array(NA, dim=c(1825, 48, 2500),
               dimnames=list(NULL, NULL, as.character(seq(1, 2500, 1))))
               ## 3th dimension = individual ID
    
  • 1个3D阵列就像:

    p <- array(NA, dim=c(1825, 38, 1000),
               dimnames=list(NULL, NULL, as.character(seq(1, 1000, 1))))
               ## 3th dimension = cell ID
    
  • 6个3D阵列如下:

    t <- array(NA, dim=c(1825, 41, 2500),
               dimnames=list(NULL, NULL, as.character(seq(1, 2500, 1))))
               ## 3th dimension = individual ID
    

数组包含数字和字符/字符串数据类型。

理想情况下,我想增加个人数量和/或补丁数量,但是由于内存问题,这是不可能的。似乎有一些可用的工具,例如bigmemorygc来管理内存。这些工具有效吗?我是编程的新手,没有管理内存和高性能计算的经验。任何建议都将不胜感激,谢谢您的宝贵时间。

2 个答案:

答案 0 :(得分:4)

据我了解,bigmemory仅适用于矩阵,而不适用于多维数组,但是您可以将多维数组另存为矩阵列表。

gc只是垃圾收集器,您不必真正调用它,因为它将被自动调用,但是手册中也指出:

  

删除大型对象后调用gc可能很有用,因为   这可能会提示R将内存返回给操作系统。

我认为对您来说最有用的软件包是ff。 这是一个简短的示例,用于说明软件包ff的强度,该软件包将数据存储在磁盘上,并且几乎不影响内存。

具有base-R的初始化数组:

p <- array(NA, dim=c(1825, 38, 1000),
           dimnames=list(NULL, NULL, as.character(seq(1, 1000, 1))))

format(object.size(p), units="Mb")
  

“ 264.6 Mb”

因此,总体而言,您的初始阵列将已占用多达5GB的内存,这将使您在繁重的计算中遇到麻烦。


带有ff的初始化数组:

library(ff)
myArr <- ff(NA, dim=c(1825, 38, 1000), 
            dimnames=list(NULL, NULL, as.character(seq(1, 1000, 1))),
            filename="arr.ffd", vmode="logical", overwrite = T)

format(object.size(myArr), units="Mb")
  

[1]“ 0.1 Mb”


平等性测试:

euqals <- list()
for (i in 1:dim(p)[1]) {
  euqals[[i]] <-  all.equal(p[i,,],
                            myArr[i,,])
}
all(unlist(euqals))
  

[1]是

答案 1 :(得分:3)

您是否必须坚持使用数组数据类型?
如果阵列中存在许多NA,则意味着您使用的内存超出了实际需要。这是R中数组的缺点。 如果您执行的操作不一定要求您的数据为数组,则应通过将其重构为data.frame来节省一些内存

下面的示例显示您的数据状态。从数组转换后,frame看起来像。请注意,我必须显式使用na.rm=FALSE,否则结果将是0行数据。

devtools::install_github("Rdatatable/data.table@as.dt.array.null.dimnames")
library(data.table)

p <- array(NA, dim=c(1825, 38, 1000),
           dimnames=list(NULL, NULL, as.character(seq(1, 1000, 1))))
as.data.table(p, na.rm=FALSE)
#             V1    V2     V3  value
#          <int> <int> <char> <lgcl>
#       1:     1     1      1     NA
#       2:     1     1     10     NA
#       3:     1     1    100     NA
#       4:     1     1   1000     NA
#       5:     1     1    101     NA

另一种方法是使用data.cube包。它基本上会在后台为您完成我上面写的内容。您仍然拥有数组的[运算符,但是data.cube对象不能与期望在输入上使用数组的R函数一起使用,因为它们会强制data.cube到数组失去所有内存的好处。 存储器的好处可能非常重要,例如data.cube vignette

array: 34.13 GB
data.cube: 0.01 GB