- ある処理をする関数 FUN( ) があるとする
- 処理 FUN( ) に渡したい入力データセットがいくつもあって、その一つ一つがlistオブジェクト X になっているとする
- コンピュータがLINUX(またはMac)のとき
- parallel パッケージを使って
library(parallel)
out <- mclapply(X,FUN)
- とするだけでよい
- こうすることで、mclapply( ) 関数が、リストX の要素を次のようなルールで処理して、返してくる(こちらのソースを読めば解る)
- もし、リストX の長さ(処理したい入力データセット数)がコンピュータのコア数以下のときは、個々のデータセットをそれぞれ異なるコアに処理させて、その結果が全部終われば、結果が返ってくる
- もし、リストX の長さがコンピュータのコア数より大きいときには、すべてのコアにまずは最初の仕事を割り振り、処理の終わったコアに、未処理の仕事を割り付けることを続ける
- 大小さまざまな行列が入力データであるときに、行列を使った計算をさせるという仕事をさせてみる
library(parallel)
n.dataset <- 10000
X <- list()
for(i in 1:n.dataset){
d <- sample(2:1000,1)
X[[i]] <- matrix(sample(1:10000,d^2,replace=TRUE),d,d)
}
my.FUN <- function(M){
for(i in 1:1000){
Minv <- solve(M)
}
return(det(Minv))
}
start_time <- Sys.time()
out1 <-mclapply(1:n.dataset,my.FUN,mc.cores=1)
end_time <- Sys.time()
print(end_time-start_time)
start_time <- Sys.time()
out2 <-mclapply(1:n.dataset,my.FUN,mc.cores=2)
end_time <- Sys.time()
print(end_time-start_time)
start_time <- Sys.time()
out3 <-mclapply(1:n.dataset,my.FUN,mc.cores=2,mc.preschedule=FALSE)
end_time <- Sys.time()
print(end_time-start_time)
- 結果、コア数2のときは単純に時間が半分になっている
>
> start_time <- Sys.time()
> out1 <-mclapply(1:n.dataset,my.FUN,mc.cores=1)
> end_time <- Sys.time()
> print(end_time-start_time)
Time difference of 14.49073 secs
>
>
> start_time <- Sys.time()
> out2 <-mclapply(1:n.dataset,my.FUN,mc.cores=2)
> end_time <- Sys.time()
> print(end_time-start_time)
Time difference of 8.580922 secs
>
>
> start_time <- Sys.time()
> out3 <-mclapply(1:n.dataset,my.FUN,mc.cores=2,mc.preschedule=FALSE)
> end_time <- Sys.time()
> print(end_time-start_time)
Time difference of 29.38319 secs
-
- なお、mc.prescheduleというオプションがあって、データセット数がそれほど多くなく、データセット間のタスクの重さにばらつきが大きいときは、mc.preschedule=FALSEを選ぶのがよいらしいが、上の例では、ばらつきは大きいものの、データセット数が多いので、ぜんぜん速くなっていない
- ちなみにWindowsの場合には、mclapply()によるパラレル処理はできない。それは、Windowsでparallelパッケージを導入して、mclapply()関数の中身を見てみると、単に、lapply()関数を(1コアで)回す仕様になっていることからも解る
> mclapply
function (X, FUN, ..., mc.preschedule = TRUE, mc.set.seed = TRUE,
mc.silent = FALSE, mc.cores = 1L, mc.cleanup = TRUE, mc.allow.recursive = TRUE)
{
cores <- as.integer(mc.cores)
if (cores < 1L)
stop("'mc.cores' must be >= 1")
if (cores > 1L)
stop("'mc.cores' > 1 is not supported on Windows")
lapply(X, FUN, ...)
}
<bytecode: 0x00000000234a5c70>
<environment: namespace:parallel>