我正在尝试解决为什么在本地计算机(具有 3 个内核)上串行运行良好且并行运行良好的进程在集群上的多个内核上运行时可能会减慢速度。我真的不能做一个最小的非工作示例,因为代码在本地工作得很好。
我已经修改了脚本以将每个工作人员的输出保存到一个文件中,稍后我会聚合这些文件——所以我不认为这是通信和聚合,除非我遗漏了一些东西。
这是我的输出。我正在为一个相当复杂的过程展示一个包装函数,然后我在运行它之前自己运行一次plyr
:
> analyze_ = function(r){#wrapper function with error handling
+ sti = proc.time()
+ out<-tryCatch(analyze(r)
+ , error=function(e) e, finally=1+1)
+ if(inherits(out, "error")) {
+ out='error!'
+ print(paste("an error happened at",r[1],r[2]))
+ }
+ print(proc.time()-sti
+ }
>
> st = proc.time()
> x = analyze_(xygrid[1,])
[1] "Successfully did -0.25 100.25"
user system elapsed
8.282 0.008 8.286
然后我并行运行代码,一切都变慢了:
> nodes <- detectCores()
> nodes
[1] 24
> registerDoMC(nodes)
> output<-a_ply(xygrid,1,analyze_, .parallel=T)
[1] "Successfully did 0.25 102.25"
user system elapsed
9.292 0.042 221.954
[1] "Successfully did 0.25 10.25"
user system elapsed
9.298 0.039 221.994
[1] "Successfully did -0.25 102.75"
user system elapsed
9.313 0.054 222.808
[1] "Successfully did -0.25 102.25"
user system elapsed
9.328 0.043 222.832
[1] "Successfully did -0.25 104.25"
user system elapsed
9.250 0.032 223.761
[1] "Successfully did -0.25 103.75"
user system elapsed
9.258 0.038 223.786
有哪些可能会导致这种行为?正如我所说,该函数会丢弃输出,在串行运行时保持基准速度,并在我的本地机器上并行运行三个内核。
这是一件事:为什么“经过”时间几乎是“用户”时间的 24 倍?(无论如何,“用户”时间是多少?)
编辑针对评论中的问题,这里是并行与串行性能的正面比较。并行实际上更慢。
> system.time(analyze_(xygrid[1,]))
user system elapsed
8.223 0.005 8.250
>
> nodes <- detectCores()
> nodes
[1] 24
> registerDoMC(nodes)
>
> system.time(a_ply(xygrid[1:24,],1,analyze_, .parallel=F))
user system elapsed
197.666 0.072 197.762
>
> system.time(a_ply(xygrid[1:24,],1,analyze_, .parallel=T))
system elapsed
119.871 0.401 206.257
Edit2 代码在登录节点上运行良好——每个作业连续需要 6 秒,并行 24 个作业需要 12 秒。那么计算节点通常与登录节点有何不同呢?
Edit3
Solved
原来我一直ibrun
在我的shell脚本中使用,它将作业发送到多个线程。但是,R 使用一种称为“线程并行性”的东西,其中并行后端是从 R 内部调用的,而不是从调用 R 作业的 shell 脚本中调用的。如果从批处理命令调用多个线程,集群将使并行作业在每个核心中运行。因此,速度大约是核心数量的倍数。所以,故事的寓意:只向批处理系统询问共享资源系统上的一个线程,并让 R 处理实际使用的核心数量。这个问题可能只与具有批处理系统的共享超级计算机相关。