使用SNOW进行MPI并行化速度缓慢

4
我的并行计算之旅还在继续。我最初安装Rmpi时遇到了困难,但我解决了这个问题(我需要sudo apt-get)。我应该说我正在运行一个带有Ubuntu 10.10的机器。
我运行了与以前的问题相同的模拟。回想一下未集群和SNOW SOCK集群的系统时间:
> system.time(CltSim(nSims=10000, size=100))
   user  system elapsed 
  0.476   0.008   0.484 
> system.time(ParCltSim(cluster=cl, nSims=10000, size=100))
   user  system elapsed 
  0.028   0.004   0.375 

现在,使用MPI集群,相对于不使用集群,速度会减慢

> stopCluster(cl)
> cl <- getMPIcluster()
> system.time(ParCltSim(cluster=cl, nSims=10000, size=100))
   user  system elapsed 
  0.088   0.196   0.604 

不确定这是否有用,但以下是有关创建的集群的信息:

> cl
[[1]]
$rank
[1] 1

$RECVTAG
[1] 33

$SENDTAG
[1] 22

$comm
[1] 1

attr(,"class")
[1] "MPInode"

[[2]]
$rank
[1] 2

$RECVTAG
[1] 33

$SENDTAG
[1] 22

$comm
[1] 1

attr(,"class")
[1] "MPInode"

attr(,"class")
[1] "spawnedMPIcluster" "MPIcluster"        "cluster"          

这里发生了什么事情有什么想法吗?感谢您在尝试这些并行化选项时提供的帮助。

诚挚地, Charlie


1
我怀疑有足够的开销导致你的运行变慢。我使用snowfall(在unix和windows上即插即用),我得到了不错的加速,但我的任务需要相当长的时间。 - Roman Luštrik
1个回答

4
这与您的另一个问题有点相似:集群节点之间的通信所占用的时间比实际函数运行时间更长。
这可以通过更改您的函数进行说明:
library(snow)
cl <- makeCluster(2)

SnowSim <- function(cluster, nSims=10,n){
  parSapply(cluster, 1:nSims, function(x){
    Sys.sleep(n)
    x
  })
}



library(foreach)
library(doSNOW)
registerDoSNOW(cl)

ForSim <- function(nSims=10,n) {
  foreach(i=1:nSims, .combine=c) %dopar% {
      Sys.sleep(n)
      i
  }
}

这样我们就可以在不同数量的模拟中模拟长时间计算和短时间计算函数。让我们考虑两种情况,一种是1秒计算和10次循环,另一种是1毫秒计算和10000次循环。两者都应该持续10秒:
> system.time(SnowSim(cl,10,1))
   user  system elapsed 
      0       0       5 

> system.time(ForSim(10,1))
   user  system elapsed 
   0.03    0.00    5.03 

> system.time(SnowSim(cl,10000,0.001))
   user  system elapsed 
   0.02    0.00    9.78 

> system.time(ForSim(10000,0.001))
   user  system elapsed 
  10.04    0.00   19.81 

基本上,你所看到的是,在需要长时间计算的函数和低模拟下,并行化版本将计算时间干净地减半,与预期相符。
现在你所做的模拟属于第二种情况。在那里,你会发现解决方案已经没有什么区别了,而解决方案甚至需要两倍的时间。这仅仅是由于节点之间通信和处理返回数据所带来的开销。与相比,foreach的开销要大得多,正如我对你以前问题的回答中所示。
我没有启动我的Ubuntu尝试使用MPI集群,但基本上故事是相同的。根据通信所需的时间,不同类型的集群之间存在细微差别部分原因是底层包之间的差异。

Jons,非常感谢你提供的清晰而巧妙的说明!我将尝试使用MPI来检查一下你的想法。我原以为每个集群都会做自己的事情,并且仅在最后加入结果,所以我预计通信的基本成本与模拟数量无关,但通信成本似乎与模拟数量呈线性增长。这使我相信集群在每次运行后进行通信——是吗?你知道何时并行运行可以节省时间,何时可能会浪费时间的一个好的经验法则吗?谢谢! - Charlie
@Charlie:我没有固定的规则,但只有在我的内部函数需要相当长时间时才使用并行化。通信是必要的,因为计算机必须知道哪个核心是空闲的,以便发送下一个命令,并且必须知道哪个结果来自哪个循环实例,以保持结果的良好顺序。 - Joris Meys

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接