2016-09-07 2 views
1

Ich habe eine lange Liste von großen Matrizen (oder Rastern), die ich parallel summieren möchte. Die Ausgabe sollte eine Matrix sein. Ich versuchte foreach mit der .combine='+' Funktion, die funktioniert, aber es scheint .Combine funktioniert nur auf einen Thread, so dass es keine Beschleunigung gibt. Irgendwelche Vorschläge? Dankparallele Summierung von Matrizen (oder Rastern) in R

matrix.list <- list() 
for(i in 1:10000) matrix.list[[i]] <- matrix(1,nrow=100,ncol=100) 

library(foreach) 
library(doMC) 
registerDoMC(cores=2) 

matrix.sum <- foreach(i=1:10000,.combine='+') %dopar% matrix.list[[i]] 
+0

genau. Ich habe 600.000 Matrizen der Größe 7200x3600 –

+0

sie sind spärlich, aber ich wollte die Dinge nicht komplizieren –

+0

Nicht eine parallele Lösung, aber 'Reduce ('+', matrix.list)' lief rund 18 mal schneller als der obige Code. – jav

Antwort

0

Ihr Problem ist, dass Sie nur matrix.list[[i]] parallel tun und [[ ist sehr schnell für Listen. Die Operation .combine wird vom Master-Prozess ausgeführt, nachdem alle parallelen Tasks abgeschlossen wurden.

Sie sollten Ihre Liste in Stücke wie folgt trennen:

set.seed(42) 
n <- 1e3 
matrix.list <- replicate(n, matrix(rnorm(1),nrow=1000,ncol=1000), simplify = FALSE) 

system.time({ 
matrix.sum_s <- Reduce("+", matrix.list) 
}) 
#user system elapsed 
#1.83 1.25 3.08 

library(foreach) 
library(doParallel) 
ncl <- 4 
cl <- makeCluster(ncl) 
registerDoParallel(cl) 

system.time({ 
matrix.sum_p <- foreach(x = split(matrix.list, (seq_len(n) - 1) %/% (n/ncl)), 
         .combine='+') %dopar% 
    {Reduce("+", x)} 
}) 
#user system elapsed 
#6.49 35.97 46.97 
stopCluster(cl) 

all.equal(matrix.sum_s, matrix.sum_p) 
#[1] TRUE 

Natürlich ist die parallelisierte Version einfach noch viel langsamer ist als Reduce verwenden. Warum? Weil + eine schnelle Low-Level-Funktion (.Primitive) ist. foreach verbringt die meiste Zeit damit, die mehreren GB dichten Matrizen zu kopieren.