R中的并行化:%dopar%vs%do%.为什么使用单核产生更好的性能?

dan*_*iel 6 parallel-processing foreach r

在使用doMC和foreach在其核心之间分配进程时,我在计算机中遇到了一种奇怪的行为.有人知道为什么使用单核我比使用2核更好的性能?正如您所看到的,处理相同的代码而不注册任何核心(据称只使用1个核心)会产生更多的时间效率处理.虽然%do%似乎比%dopar%表现更好,但注册2个核心中的2个核心会产生更多时间.

require(foreach)
require(doMC)
# 1-core
> system.time(m <- foreach(i=1:100) %dopar% 
+ matrix(rnorm(1000*1000), ncol=5000) )
   user  system elapsed 
  9.285   1.895  11.083 
> system.time(m <- foreach(i=1:100) %do% 
+ matrix(rnorm(1000*1000), ncol=5000) )
   user  system elapsed 
  9.139   1.879  10.979 

# 2-core
> registerDoMC(cores=2)
> system.time(m <- foreach(i=1:100) %dopar% 
+ matrix(rnorm(1000*1000), ncol=5000) )
   user  system elapsed 
  3.322   3.737 132.027
> system.time(m <- foreach(i=1:100) %do% 
+ matrix(rnorm(1000*1000), ncol=5000) )
   user  system elapsed 
  9.744   2.054  11.740 
Run Code Online (Sandbox Code Playgroud)

在少数试验中使用4个核心会产生截然不同的结果:

> registerDoMC(cores=4)
> system.time(m <- foreach(i=1:100) %dopar% 
{ matrix(rnorm(1000*1000), ncol=5000) } )
   user  system elapsed 
 11.522   4.082  24.444 
> system.time(m <- foreach(i=1:100) %dopar% 
{ matrix(rnorm(1000*1000), ncol=5000) } )
   user  system elapsed 
 21.388   6.299  25.437 
> system.time(m <- foreach(i=1:100) %dopar% 
{ matrix(rnorm(1000*1000), ncol=5000) } )
   user  system elapsed 
 17.439   5.250   9.300 
> system.time(m <- foreach(i=1:100) %dopar% 
{ matrix(rnorm(1000*1000), ncol=5000) } )
   user  system elapsed 
 17.480   5.264   9.170
Run Code Online (Sandbox Code Playgroud)

krl*_*mlr 8

这是结果的组合,占用了所有处理时间.cores=2如果没有返回结果,这些是我的机器上的时间安排.它本质上是相同的代码,只丢弃创建的矩阵而不是返回:

> system.time(m <- foreach(i=1:100) %do% 
+ { matrix(rnorm(1000*1000), ncol=5000); NULL } )
   user  system elapsed 
 13.793   0.376  14.197 
> system.time(m <- foreach(i=1:100) %dopar% 
+ { matrix(rnorm(1000*1000), ncol=5000); NULL } )
   user  system elapsed 
  8.057   5.236   9.970 
Run Code Online (Sandbox Code Playgroud)

仍然不是最优的,但至少并行版本现在更快.

这来自以下文件doMC:

doMC软件包使用软件包的多核功能为foreach/ %dopar%function 提供并行后端 parallel.

现在,parallel使用一种fork机制来生成R进程的相同副本.从单独的过程中收集结果是一项昂贵的任务,这是您在时间测量中看到的.