我正在研究一个需要具有大量零的大型矩阵的项目。不幸的是,由于这些矩阵中的一些可能有超过 1e10 个元素,因此由于 RAM 限制,不能使用“标准”R 矩阵。另外,我需要在多个内核上工作,因为计算可能需要很长时间,而且确实不应该。
到目前为止,我一直在使用该foreach
包,然后将结果(以标准矩阵形式出现)转换为稀疏矩阵。我忍不住想,一定有更聪明的办法。
这是我到目前为止所做的一个最小示例:
cl <- makeSOCKcluster(8)
registerDoSNOW(cl)
Mat <- foreach(j=1:length(lambda), .combine='cbind') %dopar% {
replicate(iter, rpois(n=1, lambda[j]))
}
Mat <- Matrix(Mat, sparse=TRUE)
stopCluster(cl)
lambda 都非常小,因此只有大约每 5 个元素不为零,因此将结果存储在稀疏矩阵中是明智的。
不幸的是,现在必须将迭代次数从 1e6 增加到至少 1e7,这样foreach
循环生成的矩阵太大而无法存储在 8GB 的 RAM 中。我现在要做的是将任务拆分为每个具有 1e6 次迭代的步骤,并将它们组合成一个单一的稀疏矩阵。
我现在有以下想法:
library(Matrix)
library(snow)
cl <- makeSOCKcluster(8)
iter <- 1e6
steps <- 1e5
numsteps <- iter / steps
draws <- function(x, lambda, steps){
replicate(n=steps, rpois(n=1, lambda=lambda))
}
for(i in 1:numsteps){
Mat <- Matrix(0, nrow=steps, ncol=96, sparse=TRUE)
Mat <- Matrix(
parApply(cl=cl, X=Mat, MARGIN=2, FUN=draws, lambda=0.2, steps=steps)
, sparse = TRUE)
if(!exists("fullmat")) fullmat <- Mat else fullmat <- rBind(fullmat, Mat)
rm(Mat)
}
stopCluster(cl)
It works fine, but I had to fix lambda to some value. For my application, I need the values in the ith row to come from a poisson distribution with mean equal to the ith element of the lambda vector. This obviously worked fine in the foreach
loop., but I have yet to find a way to make it work in an apply loop.
My questions are:
- Is it possible to have the apply function "know" on which row it is operating and pass a corresponding argument to a function?
- Is there a way to work with foreach and sparse matrices without the need of creating a standard matrix and converting it into a sparse one in the next step?
- 如果以上都不是,我有没有办法手动将任务分配给 R 的从属进程 - 也就是说,我可以具体告诉一个进程在第 1 列上工作,另一个在第 2 列上工作,依此类推,每个创建一个稀疏向量,并且仅在最后一步中组合这些向量。