adn*_*bps 7 memory memory-management r
我正在尝试扩展一个大矩阵(我实际使用的矩阵要大得多):
x = matrix(rnorm(1e8), nrow=1e4)
x = scale(x)
Run Code Online (Sandbox Code Playgroud)
该矩阵使用~800 MB的内存.但是,使用lineprof,我看到scale函数分配了9.5 GB的内存,并在完成运行后释放8.75 GB.因为这个函数的内存效率很低,所以当我运行它时,它有时会崩溃我的会话.
我试图找到一种内存有效的方法来运行此功能.如果我自己编写代码,它只分配~6.8 GB,但这看起来仍然很多:
x = matrix(rnorm(1e8), nrow=1e4)
u = apply(x, 2, mean)
s = apply(x, 2, sd)
x = t((t(x) - u)/s)
Run Code Online (Sandbox Code Playgroud)
我认为通过将x列分成组,然后分别缩放每个列组,我可以做得更好:
x = matrix(rnorm(1e8), nrow=1e4)
g = split(1:ncol(x), ceiling(1:ncol(x)/100))
for(j in g){
x[,j] = scale(x[,j])
}
Run Code Online (Sandbox Code Playgroud)
有了profvis,我发现总的来说这个功能效率很低.它分配10.8 GB内存并释放10.5 GB.但是,我认为R可能在for循环中进行垃圾收集,但它不是这样做的,因为它不需要.它是否正确?如果是这样,那么这可能是最好的选择吗?
问题:
• 编写这些函数以避免内存崩溃的最佳方法是什么?(如果包装可用,甚至更好)
• 在分析代码时如何计算垃圾回收?我的理解是,除非需要,否则GC并不总是运行.
更新:就运行时而言,将列拆分为10组并不比使用scale(x)函数慢得多.在[1000 x 1000]矩阵上运行两个函数,使用微基准测试评估的平均运行时间为:
•scale(x)= 154 ms
•拆分为10个列组= 167毫秒
•拆分为1000个列组(即分别缩放每列)= 373 ms
Raf*_*íaz -1
adn bps感谢关于内存使用的评论修改我的答案。首先我使用gc{base}垃圾收集功能来释放一些内存。
gc()
used (Mb) gc trigger (Mb) max used (Mb)
Ncells 684317 36.6 1168576 62.5 940480 50.3
Vcells 1053307 8.1 2060183 15.8 1359327 10.4
gc(reset = TRUE)
used (Mb) gc trigger (Mb) max used (Mb)
Ncells 684296 36.6 1168576 62.5 684296 36.6
Vcells 1053271 8.1 2060183 15.8 1053271 8.1
Run Code Online (Sandbox Code Playgroud)
我找到了一个我认为可以帮助你的表格,首先我使用 Rcpp 包生成 rnorm 矩阵,使用 c++ 代码,它加快了过程一点
library(Rcpp)
cppFunction('NumericVector ranM(int n, int m) {
NumericVector v = rnorm(n * m);
v.attr("dim") = Dimension(n, m);
return v;
}')
system.time(x <- ranM(1e4,1e4))
user system elapsed
7.19 0.09 7.30
system.time(y<- matrix(rnorm(1e8), nrow=1e4))
user system elapsed
10.67 0.42 11.09
Run Code Online (Sandbox Code Playgroud)
矩阵的大小x和y是相同的
print(object.size(x), units = "auto")
762.9 Mb
print(object.size(y), units = "auto")
762.9 Mb
#system.time(w <- scale(x))
# user system elapsed
# 11.86 5.79 221.54 without using gc(TRUE)
system.time(w <- scale(x))
user system elapsed
9.52 5.39 47.33 using gc(TRUE)
remove(w,y)
Run Code Online (Sandbox Code Playgroud)
我加载库data.table, ,并将矩阵 x 转换为 data.table 类,以使用缩放函数
library(data.table)
system.time(z <- data.table(x))
system.time(z <- data.table(x))
user system elapsed
1.18 0.33 1.55
system.time(z<-z[, lapply(.SD, scale)])
user system elapsed
8.34 0.21 8.58
print(object.size(z), units = "auto")
763.5 Mb
Run Code Online (Sandbox Code Playgroud)
现在我使用bigmemory库来有效利用内存,并且如果需要的话我会删除原始矩阵x,以免环境中积累重物
library(bigmemory)
system.time(z <- as.big.matrix(z))
user system elapsed
15.90 6.64 23.34
print(object.size(x), units = "b")/print(object.size(z), units = "auto")
800000200 bytes
664 bytes
1204819.6 bytes
remove(x)
gc()
used (Mb) gc trigger (Mb) max used (Mb)
Ncells 783279 41.9 1442291 77.1 1442291 77.1
Vcells 1180947 9.1 461812104 3523.4 601095521 4586.0
Run Code Online (Sandbox Code Playgroud)
经过的时间显示出相当大的时间改进,大约快了 5 倍。请注意,bigmatrix 对象小了 100 万倍。您可以重现一个简短的示例,以查看矩阵和 bib.matrix 中的比例结果是否相等
set.seed(1)
m1 <- matrix(rnorm(5*5), nrow = 5)
m2 <- as.big.matrix(m1)
class(m2)
[1] "big.matrix"
attr(,"package")
[1] "bigmemory"
scale(m1) == scale(m2[,])
[,1] [,2] [,3] [,4] [,5]
[1,] TRUE TRUE TRUE TRUE TRUE
[2,] TRUE TRUE TRUE TRUE TRUE
[3,] TRUE TRUE TRUE TRUE TRUE
[4,] TRUE TRUE TRUE TRUE TRUE
[5,] TRUE TRUE TRUE TRUE TRUE
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
147 次 |
| 最近记录: |