Kar*_*l A 4 parallel-processing r
我是 R 中并行计算的新手,希望使用并行包来加速我的计算(这比下面的示例更复杂)。然而,与通常的 lapply 函数相比,使用 mclapply 函数时的计算时间要长得多。
\n\n我在笔记本电脑上安装了全新的 Ubuntu 18.04.2 LTS,它具有 7.7 GB 内存和 Intel\xc2\xae Core\xe2\x84\xa2 i7-4500U CPU @ 1.80GHz \xc3\x97 4 处理器。我在 R studio 上运行 R。
\n\nrequire(parallel)\n\na <- seq(0, 1, length.out = 110) #data\nb <- seq(0, 1, length.out = 110)\nc <- replicate(1000, sample(1:100,size=10), simplify=FALSE)\n\nfunction_A <- function(i, j, k) { # some random function to examplify the problem\n i+ j * pmax(i-k,0) \n}\n\n#running it with mclapply \nptm_mc <- proc.time() \noutput <- mclapply(1:NROW(c), function(o){ \n mclapply(1:NROW(a),function(p) function_A(a[p], b, c[[o]]))})\ntime_mclapply <- proc.time() - ptm_mc\n\n# running it with lapply\nptm_lapply <- proc.time() \noutput <- lapply(1:NROW(c), function(o){\n lapply(1:NROW(a),function(p) function_A(a[p], b, c[[o]]))})\ntime_lapply <- proc.time() - ptm_lapply\nRun Code Online (Sandbox Code Playgroud)\n\nlapply 的结果比 mclapply 结果快得多:
\n\n > time_mclapply\n user system elapsed \n 6.030 439.112 148.088 \n > time_lapply\n user system elapsed \n 1.662 0.165 1.827 \nRun Code Online (Sandbox Code Playgroud)\n\n为什么我会得到这个结果?是因为我的设置还是常见问题?\n我怎样才能获得实际上比 lapply 结果更快的结果,从而使整个过程更快?
\n\n更新:\n嵌套循环的两个剩余组合的更新:
\n\nptm_mc_OUT <- proc.time() \noutput <- mclapply(1:NROW(c), function(o){\n lapply(1:NROW(a),function(p) function_A(a[p], b, c[[o]]))})\n time_mclapply_OUT <- proc.time() - ptm_mc_OUT\n\nptm_mc_IN <- proc.time() \noutput <- lapply(1:NROW(c), function(o){\n mclapply(1:NROW(a),function(p) function_A(a[p], b, c[[o]]))})\ntime_mclapply_IN <- proc.time() - ptm_mc_IN\n\n require(dplyr)\ntimes <- rbind(time_mclapply,\n time_lapply,\n time_mclapply_OUT, \n time_mclapply_IN) %>% data.frame()\n\ntimes\nRun Code Online (Sandbox Code Playgroud)\n\n这给了我们
\n\n>times\n user.self sys.self elapsed user.child sys.child\ntime_mclapply 0.075 0.081 22.621 1.933 34.266\ntime_lapply 1.070 0.049 1.118 0.000 0.000\ntime_mclapply_OUT 0.064 0.077 0.884 2.539 34.587\ntime_mclapply_IN 1.329 31.843 37.426 5.108 28.879\nRun Code Online (Sandbox Code Playgroud)\n\n在另一次运行中我得到了(所以运行时间似乎变化很大,有没有更好的方法来显示它们?)
\n\ntimes_lapply\n user.self sys.self elapsed user.child sys.child\ntime_mclapply 0.324 0.121 9.108 0.000 0.000\ntime_lapply 1.060 0.049 1.108 0.000 0.000\ntime_mclapply_OUT 0.211 0.092 1.155 10.791 19.632\ntime_mclapply_IN 1.221 22.196 27.089 5.130 23.032\nRun Code Online (Sandbox Code Playgroud)\n
令 N 为机器的线程数。一些建议:
您不应使用两个级别的并行性,因为您将使用 N^2 线程。
您应该尝试在外部循环而不是内部循环中进行并行化(因为并行性的开销只会发生一次)。
您不应该使用所有线程(人们通常使用 N-1 或 N/2)。
当使用 N/2 ( mc.cores = parallel::detectCores() / 2) 时,time_mclapply_OUT速度是 的两倍time_lapply。