我想知道是否有办法让R中的foreach包使用预先分配的结构来放置结果。基本上它涉及很多大型数据集上的小型linalg操作。
我的非foreach原始代码类似于
results <- rep(NA,m*l*[big.number])
dim(results) <- c(m,l,[big.number])
for (i in 1:m){
for (j in 1:l){
results[i,j,] <- function(j,i,data)
}
}
我想使用foreach和doMC来并行化这个,但测试运行真的非常慢,我认为这是rbind和c所做的持续数据移动。
答案 0 :(得分:2)
这不是答案,但我想我会发布一些测试结果,希望其他人知道发生了什么:
> data <- matrix(rnorm(1000 * 10000), nrow=10000)
> system.time(foreach(j=1:1000, .combine = function(...) NULL, .multicombine=TRUE) %do% { sum(data[,j]) })
utilisateur système écoulé
0.643 0.031 0.674
> system.time(foreach(j=1:1000, .combine = function(...) NULL, .multicombine=TRUE) %dopar% { sum(data[,j]) })
utilisateur système écoulé
0.613 0.215 0.653
> system.time(foreach(j=1:1000) %dopar% { sum(data[,j]) })
utilisateur système écoulé
0.537 0.122 0.745
> system.time(foreach(j=1:1000) %do% { sum(data[,j]) })
utilisateur système écoulé
0.650 0.028 0.681
> system.time (for (j in 1:1000) { sum(data[,j]) })
utilisateur système écoulé
0.153 0.069 0.222
简而言之,使用内置for
仍然比串行foreach
更快。你并没有真正使用dopar
赢得胜利,似乎并不是把所有东西放在一起就是一直在进行的(可能仍然需要将数据传回主人需要很长时间)。你也可以说,通过计算这么简单,开销自然会占主导地位。所以让我们做一些更复杂的事情:
> data <- matrix(rnorm(3000 * 10000), nrow=10000)
> system.time (for(j in 1:6000) { sum(lgamma(exp(data[,(j - 1) %% 3000 + 1]))) })
utilisateur système écoulé
11.215 1.272 12.490
> system.time (foreach(j=1:6000, .combine=c) %do% { sum(lgamma(exp(data[,(j - 1) %% 3000 + 1]))) })
utilisateur système écoulé
14.304 0.468 15.788
> system.time (foreach(j=1:6000, .combine=c) %dopar% { sum(lgamma(exp(data[,(j - 1) %% 3000 + 1]))) })
utilisateur système écoulé
14.377 11.839 10.358
现在dopar
开始胜出,但这三者仍然具有可比性,内置for
并不是那么糟糕,即使有了额外的工作。但是沟通开销呢?我们只返回转换后的数据(每次迭代10,000个数字),而不是取总和。
> system.time (for(j in 1:6000) { lgamma(exp(data[,(j - 1) %% 3000 + 1])) })
utilisateur système écoulé
11.092 1.189 12.302
> system.time (foreach(j=1:6000, .combine=function (...) NULL, .multicombine=TRUE) %do% { lgamma(exp(data[,(j - 1) %% 3000 + 1])) })
utilisateur système écoulé
14.902 1.867 22.901
> system.time (foreach(j=1:6000, .combine=function (...) NULL, .multicombine=TRUE) %dopar% { lgamma(exp(data[,(j - 1) %% 3000 + 1])) })
^C
Timing stopped at: 2.155 0.706 241.948
>
在这里,for
循环不需要为保持结果而烦恼,需要与之前一样长。这次%do%
版本耗费了很长时间。 %dopar%
可能通过共享内存传输结果?我决定在大约4分钟后杀死它。
答案 1 :(得分:0)
也许我在这里遗漏了一些东西。单个函数(i,j,data)调用的成本应该是在for
- 循环中调用还是通过foreach
调用的。您是否可以在串行模式下尝试foreach
,然后尝试multicore
(除非您在Windows上)并从那里开始?
答案 2 :(得分:0)
我很幸运abind()(来自图书馆(abind))。例如,假设我有一个返回矩阵的模拟函数,我想要一个大数组,我可以使用abind(,沿= .5)来获取要绑定到数组中的矩阵列表,并添加一个新的维度。所以你可能喜欢这样的东西:
myfun<-function(arr){abind(arr,along=.5)}
foreach(1:n.sims,.combine=myfun) ....