我有一个嵌套的*apply
调用,我希望将它们并行化。我可以选择在顶部调用或嵌套内部调用上并行化。我相信,理论上,第一个应该更好,但我的问题是我有4个核心,但最外面的对象有5个部分是非常不同的大小。当我运行第一个例子时,所有4个核心运行大约10分钟,然后其中2个核心完成。 1小时后,第3个完成,第4个是最后一个以1:45结束,获得了两个最大的进程。
每个人的专业和意见是什么?
parLapply(cl, object, function(obj) lapply(obj, funct))
-- OR --
lapply(object, function(obj) parLapply(cl, obj, funct))
此外,有没有办法手动分配负载?这样我就可以将两个大对象分开并将两个最小的对象放在一起。
编辑:一般来说,CS理论对这种情况有何看法?这通常是并行呼叫的最佳位置(不包括这样的特殊情况)
答案 0 :(得分:0)
parLapply
将您的任务分组,因此每个群集工作者有一组任务。如果您需要负载平衡,那么效果不佳,因此我建议您尝试使用clusterApplyLB
:
clusterApplyLB(cl, object, function(obj) lapply(obj, funct))
如果您有5个任务和4个工作人员,这将在工作人员1-4上安排任务1-4,然后它将在完成任务的工作人员上安排任务5。这可能相当不错,但如果最后一项任务最短,它会更好。
如果您使用:
lapply(object, function(obj) clusterApplyLB(cl, obj, funct))
它将执行5个单独的并行作业。如果这些并行作业中的任务很小,那么这可能是非常低效的,而且对于有负载平衡问题的5个作业中的每一个都会浪费资源。因此,这种方法通常效果不佳。
您通常希望使用第一种情况,但是当任务数量不比工作人员数量多很多时,负载平衡通常是一个严重的问题。如果每次调用funct
需要一段合理的时间(例如,至少几秒钟),您可以尝试使用foreach包中的嵌套运算符展开循环:
r <-
foreach(obj=object) %:%
foreach(o=obj) %dopar% {
funct(o)
}
这会将所有对funct
的调用转换为单个任务流,但仍会将结果返回到列表列表中。
您可以在我写的名为Nesting Foreach Loops的插图中找到有关使用foreach嵌套运算符的更多信息。