mclapply()的性能明显比lapply()差。我如何加快速度?

时间:2019-02-12 11:56:04

标签: r parallel-processing

我是R中并行计算的新手,并且想使用并行包来加快我的计算速度(这比下面的示例要复杂得多)。但是,与通常的lapply函数相比,使用mclapply函数时,计算所需的时间更长。

我在笔记本电脑上安装了一个新的Ubuntu 18.04.2 LTS,它具有7.7 GB内存和1.80GHz×4处理器的Intel®Core™i7-4500U CPU。我正在R Studio上运行R。

require(parallel)

a <- seq(0, 1, length.out = 110) #data
b <-  seq(0, 1, length.out = 110)
c <- replicate(1000, sample(1:100,size=10), simplify=FALSE)

function_A <- function(i, j, k) { # some random function to examplify the problem
  i+ j * pmax(i-k,0) 
}

#running it with mclapply 
ptm_mc <- proc.time()  
output <- mclapply(1:NROW(c), function(o){ 
  mclapply(1:NROW(a),function(p) function_A(a[p], b, c[[o]]))})
time_mclapply <- proc.time() - ptm_mc

# running it with lapply
ptm_lapply <- proc.time()  
output <- lapply(1:NROW(c), function(o){
  lapply(1:NROW(a),function(p) function_A(a[p], b, c[[o]]))})
time_lapply <- proc.time() - ptm_lapply

lapply的结果比mclapply的结果快很多:

 > time_mclapply
       user      system     elapsed 
      6.030     439.112     148.088 
 > time_lapply
       user      system     elapsed 
      1.662       0.165       1.827 

为什么会得到这个结果?是因为我的设置还是常见问题? 我怎样才能得到比实际结果更快的结果,所以整个过程会更快?

更新: 嵌套循环的其余两个组合的更新:

ptm_mc_OUT <- proc.time()  
output <- mclapply(1:NROW(c), function(o){
  lapply(1:NROW(a),function(p) function_A(a[p], b, c[[o]]))})
 time_mclapply_OUT <- proc.time() - ptm_mc_OUT

ptm_mc_IN <- proc.time()  
output <- lapply(1:NROW(c), function(o){
  mclapply(1:NROW(a),function(p) function_A(a[p], b, c[[o]]))})
time_mclapply_IN <- proc.time() - ptm_mc_IN

 require(dplyr)
times <- rbind(time_mclapply,
                      time_lapply,
                      time_mclapply_OUT, 
                      time_mclapply_IN) %>% data.frame()

times

这给了我们

>times
                  user.self sys.self elapsed user.child sys.child
time_mclapply         0.075    0.081  22.621      1.933    34.266
time_lapply           1.070    0.049   1.118      0.000     0.000
time_mclapply_OUT     0.064    0.077   0.884      2.539    34.587
time_mclapply_IN      1.329   31.843  37.426      5.108    28.879

在另一次运行中我得到了(所以运行时间似乎相差很大,是否有更好的显示方式?)

times_lapply
                   user.self sys.self elapsed user.child sys.child
time_mclapply         0.324    0.121   9.108      0.000     0.000
time_lapply           1.060    0.049   1.108      0.000     0.000
time_mclapply_OUT     0.211    0.092   1.155     10.791    19.632
time_mclapply_IN      1.221   22.196  27.089      5.130    23.032

1 个答案:

答案 0 :(得分:1)

让N为您计算机的线程数。一些建议:

  1. 不应使用两个并行级别,因为将使用N ^ 2个线程。

  2. 您应该尝试在外部循环而不是内部循环中并行化(因为并行性的开销只会发生一次)。

  3. 您不应该使用所有线程(人们通常使用N-1或N / 2)。

使用N / 2(mc.cores = parallel::detectCores() / 2)时,time_mclapply_OUT的速度是time_lapply的两倍。