【发布时间】:2018-09-22 19:47:58
【问题描述】:
我正在尝试缩放一个大矩阵(我实际使用的矩阵要大得多):
x = matrix(rnorm(1e8), nrow=1e4)
x = scale(x)
此矩阵使用约 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)
我认为通过将 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])
}
使用 profvis,我发现这个功能总体上效率较低。它分配 10.8 GB 内存并释放 10.5 GB。但是,我认为 R 可能可以在 for 循环中进行垃圾收集,但它没有这样做,因为它不需要。它是否正确?如果是这样,那么这可能是最好的选择?
问题:
• 编写此类函数以避免内存崩溃的最佳方法是什么?(如果有可用的包,那就更好了)
• 如何在分析代码时考虑垃圾收集?我的理解是,除非需要,否则 GC 并不总是运行。
更新:就运行时间而言,将列分成 10 组并不比使用 scale(x) 函数慢多少。在 [1000 x 1000] 矩阵上运行这两个函数,使用微基准评估的平均运行时间为:
• 比例 (x) = 154 毫秒
• 分成 10 个列组 = 167 毫秒
• 分成 1000 个列组(即分别缩放每列)= 373 毫秒
【问题讨论】:
-
我可能会查看 matrixStats 包以计算列均值和 SD,然后使用这些手动进行。我还想知道是否直接使用列均值/标准差创建带有 byrow = TRUE 的矩阵,然后进行减法/除法可能比所有转置更快。
标签: r memory memory-management