开发者

Memory Usage in Foreach Function

I was wondering if there is any way to get the foreach packag开发者_Go百科e in R to use a pre-allocated structure to put results. basically it involves lots of small linalg operations on very big data sets.

My non-foreach original code is something like

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)
    }
}

I'd like to use foreach and doMC to parallelize this but test runs are really really slow and I think it's the continual data moving that rbind and c do.


This is not an answer, but I thought I'd post some test results in hopes that someone else will know what's going on:

> 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 

In short, using the builtin for is still way faster than serial foreach. You don't really win by using dopar, and it doesn't seem that putting everything together is what's taking all the time (it could still be that transmitting the data back to the master takes a long time). You can also argue that with computation this simple, the overhead will naturally dominate. So let's do some more complicated stuff:

> 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 

Now dopar is starting to win out but the three are still pretty comparable and the builtin for is not so bad, even with all the additional work. But what about communication overhead? Instead of taking sums, we'll just return the transformed data (10,000 numbers per iteration).

> 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 
> 

Here, the for loop which doesn't have to bother with keeping results around takes about as long as before. The %do% version took a lot longer this time. And the %dopar% which is probably transferring the results through shared memory? I decided to kill it after about 4 minutes.


I've had luck with abind() (from library(abind)). For example, say I have a simulation function returning matrices and I'd like a big array, I could use abind(,along=.5) to get the list of matrices to be bound into an array with a new dimension added to it. So you might like something like:

myfun<-function(arr){abind(arr,along=.5)}

foreach(1:n.sims,.combine=myfun) .... 


Maybe I am missing something here. The cost of single function(i,j,data) call should be invariant to whether it is called in a for-loop or via foreach. Can you not try foreach in serial mode, then maybe try with multicore (unless you're on Windows) and go from there?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜