1

並列に合計したい大きな行列 (またはラスター) の長いリストがあります。出力は行列である必要があります。foreach機能する関数を使用してみまし.combine='+'たが、.combine は 1 つのスレッドでしか機能しないため、スピードアップはありません。助言がありますか?ありがとう

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

1 に答える 1

0

あなたの問題はmatrix.list[[i]]、並列でのみ実行し[[、リストに対して非常に高速であることです。操作は、.combineすべての並列タスクが完了した後にマスター プロセスによって実行されます。

リストを次のようにチャンクに分割する必要があります。

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

もちろん、並列化されたバージョンは、単に を使用するよりもはるかに遅くなりますReduce。なんで?+は高速な低レベル ( .Primitive) 関数だからです。foreachは、数 GB の密行列をコピーすることにほとんどの時間を費やしています。

于 2016-09-07T08:33:38.423 に答える