我需要运行一个昂贵的算法320次。我可以很容易地将其并行化到4个集群上,每个集群运行80次迭代。我可以访问一台32核的机器,所以我想进一步并行处理这个问题。将80个迭代组并行化比较困难,但这是可能的。我的想法是在每个主集群上运行8个子集群,每个集群处理10次迭代。
为了测试这个想法,我使用R中的并行包实现了下面的虚拟代码。我在4个内核上测试了它,结果很惊讶。
正态变量发生器
方法1:在2个集群上并行一次
library(parallel)
library(tictoc)
N <- 6*10^8 # total number of observations to generate
n.threads <- 2
sample.sizes <- rep(round(N/n.threads, 0), n.threads) # Each cluster generates half of the sample
tic()
cl <- makeCluster(n.threads)
list <- parLapply(cl, sample.sizes, rnorm)
stopCluster(cl)
v <- unlist(list)
toc()
rm(list, v); gc()
36秒执行时间;50%CPU使用率
方法二:先并行2个以上的簇,然后再将每个簇再并行到2个簇上
library(parallel)
library(tictoc)
N <- 6*10^8 # total number of observations to generate
rnorm.parallel <- function(N.inside){
n.threads.inside <- 2
sample.sizes <- rep(round(N.inside/n.threads.inside, 0), n.threads.inside) # each sub thread generates 1*10^8 obs
cl.inside <- makeCluster(n.threads.inside)
list <- parLapply(cl.inside, sample.sizes, rnorm)
stopCluster(cl.inside)
v <- unlist(list)
return(v)
}
n.threads <- 2
sample.sizes <- rep(round(N/n.threads, 0), n.threads) # each main thread generates 2*10^8 obs
tic()
cl <- makeCluster(length(sample.sizes))
clusterEvalQ(cl, library(parallel))
list <- parLapply(cl, sample.sizes, rnorm.parallel)
stopCluster(cl)
v <- unlist(list)
toc()
rm(list, v); gc()
42秒执行时间;100%CPU使用率
我的结论是,虽然在集群中运行集群的技术是可行的,但是额外的开销会降低效率。有没有其他的方法可以帮助我?