在我当前的项目中,我有一个计算函数,该函数在向量 A 的一个元素上运行,并返回一个列表元素,该元素插入到列表 B 中。返回元素包含许多与第一个列表相关的任意大小的大型矩阵.
作为示例,我们采用一个函数,该函数接受原始数字 n 并生成 n x n 的随机矩阵。
vector.A <- sample(1:2000, 15000, replace = TRUE)
list.B <- as.list(rep(NA, length(vector.A)))
arbitraryMatrix <- function(n) {
matrix(rnorm(n*n), ncol = n, nrow = n)
}
for ( i in which(is.na(list.B)) ) {
print(i)
list.B[[i]] <- arbitraryMatrix( vector.A[i] )
}
这个函数会减慢较大的 list.B 的获取速度(事实上,我很确定它会在完成循环之前使 R 崩溃)。我发现 list.B 的元素在创建后就不再被访问,因此可以将其写入磁盘,而不是以减慢计算速度的方式占用内存。
我可以编写一个脚本,通过将 block 保存到 .rda 文件中来完成此操作,但我希望有人有一个更优雅的解决方案。
FF 包看起来是一个有趣的可能性 http://cran.r-project.org/web/packages/ff/ff.pdf 但据我所知它不支持列表对象。
注意事项:
- 我使用 for 循环是因为我希望能够修复第 7000 次迭代中出现的错误,而不必不必要地重新运行前 6999 次迭代。
- 根据您的机器编辑代码的参数,直到它可以运行,但在您的机器上运行速度很慢
电脑。 - 我遇到的实际问题需要一个列表作为输入,因此我对向量化任意矩阵函数不感兴趣。
- 内存问题在我的实际问题中变得更加复杂,因为该函数使用大量内存(它涉及对数据帧进行子集化)。
编辑:我正在考虑将 r 对象映射到临时文件的 mmap 包,但我仍在尝试找出如何使用它来解决这个问题。
最佳答案
这是使用 filehash 的答案包裹。这是一个很好的方法,因为它的内存占用量非常小,并且随着功能的进展几乎不会增加。这样就实现了您的目标之一。
但是,这是一个糟糕的方法,因为它有两个重大缺点......(1)它非常慢,如果您打开进程监视器,您可以看到磁盘和内存交换正在进行相当悠闲的速度(至少在我的机器上)。事实上,它太慢了,我不确定它是否会随着时间的推移而变慢。我还没有运行它完成,只是刚刚过了当我在内存中运行该函数时出现错误的点(大约第 350 项左右),以说服自己它比在内存中运行更好(此时磁盘对象为 73 GB)。这是第二个缺点,创建的磁盘对象非常庞大。
因此,希望其他人能够对您的问题提供更好的答案(也许使用 mmap
?),我最有兴趣看到。
# set up disk storage object
library(filehash)
dbCreate("myTestDB")
db <- dbInit("myTestDB")
# put data on disk
db$A <- sample(1:2000, 15000, replace = TRUE)
db$B <- as.list(rep(NA, length(db$A)))
# function
arbitraryMatrix <- function(n) {
matrix(rnorm(n*n), ncol = n, nrow = n)
}
# run function by accessing disk objects
for ( i in which(is.na(db$B)) ) {
print(i)
db$B[[i]] <- arbitraryMatrix( db$A[i] )
}
# run function by accessing disk objects, following
# Jon's comment to treat db as a list
for ( i in which(is.na(db$B)) ) {
print(i)
db[[as.character(i)]] <- arbitraryMatrix( db$A[i] )
}
# use db[[as.character(1)]] etc to access the list items
关于r - 如何以内存有效的方式将结果保存在列表中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16837148/