在R中并行异构任务的实现:使用foreach、doMC和doParallel。

3
这是困扰我的问题:
当您使用foreach调度一系列在内容上同质但在处理时间上异质(事先不知道)的任务时,它如何将这些尴尬并行任务按顺序处理?
例如,我注册了4个线程registerDoMC(cores=4),我有10个任务,第4个和第5个任务的处理时间比其他所有任务加起来都长。那么第一批显然是第1、2、3和4个任务。当第1、2和3个任务完成后,foreach如何按顺序分配其他任务?这是随机的吗(从我的观察中似乎是这样的)?如果发现某些任务需要更长的时间来处理,有什么好的做法可以加快速度?
很抱歉没有提供具体的例子,因为我的实际项目/代码涉及更多...
非常感谢任何经验/指导/提示!

如果我没记错的话,它会将任务分割并发送到实例进行处理。例如,一个由1至6的任务向量将被分割为1、2、3和4、5、6,并发送到两个工作进程。如果使用负载均衡,则这可能不适用,而调度会以不同的方式进行。希望有人能够加入并提供一个更全面的答案。 - Roman Luštrik
1个回答

6

doMC包是mclapply的包装器,默认情况下,mclapply会对任务进行预调度,这意味着它将任务分成组或块。其中一个扭曲点是它以循环调度的方式预先安排这些任务。因此,如果您有10个任务和4个工作进程,则任务分配如下:

  • 工作进程1:任务1、5、9
  • 工作进程2:任务2、6、10
  • 工作进程3:任务3、7
  • 工作进程4:任务4、8

如果你很幸运,即使任务长度非常不同,这也会给出合理的性能,但在doMC中可以禁用预调度,方法如下:

opts <- list(preschedule=FALSE)
results <- foreach(i=1:10, .options.multicore=opts) %dopar% {
    # ...
}

这将导致doMC使用mc.preschedule=FALSE选项调用mclapply,因此任务将分配给工作人员,以便它们在完成先前的任务后进行负载平衡。

似乎mc.preschedule=FALSE是最常被需要的选项。为什么它不是默认设置呢? - ctbrown
@ctbrown 我不知道Simon Urbanek编写mclapply时的想法,但是预调度对于小任务确实非常有效,并且负载平衡通常是不必要的。轮询调度往往可以避免计算时间逐渐增加或减少的任务问题。实际上,这种选择似乎已经非常成功了。 - Steve Weston

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