何时使用 parallel 与 pmap
Julia 文档建议这样做
pmap()
是针对每个函数调用执行大量工作的情况而设计的。相比之下,@ parallel for 可以处理每次迭代很小的情况,也许只是将两个数相加。
有几个原因。首先,pmap
会带来更大的启动成本,从而为员工创造就业机会。因此,如果作业非常小,这些启动成本可能变得低效。然而,相反,pmap
在工人中分配工作的聪明工作。特别是,它构建了一个作业队列,并在该工作人员可用时向每个工作人员发送新作业。相比之下,@parallel
将所有工作分配给工人。因此,如果一些工人的工作时间比其他工人长,那么你最终可能会遇到这样的情况,即大多数工人已经完成并且闲置,而少数工人在过长的时间内仍然活跃,完成工作。然而,这种情况不太可能发生在非常小而简单的工作中。
以下说明了这一点:假设我们有两个工人,其中一个工作缓慢,另一个工作速度快两倍。理想情况下,我们希望快速工作者的工作量是慢工作者的两倍。 (或者,我们可以有快速和慢速的工作,但校长完全相同)。pmap
会完成这个,但是 @parallel
不会。
对于每个测试,我们初始化以下内容:
addprocs(2)
@everywhere begin
function parallel_func(idx)
workernum = myid() - 1
sleep(workernum)
println("job $idx")
end
end
现在,对于 @parallel
测试,我们运行以下内容:
@parallel for idx = 1:12
parallel_func(idx)
end
并获得打印输出:
julia> From worker 2: job 1
From worker 3: job 7
From worker 2: job 2
From worker 2: job 3
From worker 3: job 8
From worker 2: job 4
From worker 2: job 5
From worker 3: job 9
From worker 2: job 6
From worker 3: job 10
From worker 3: job 11
From worker 3: job 12
它几乎是甜蜜的。工人们平均分享了工作。请注意,每个工作人员已完成 6 个工作,即使工人 2 的工作速度是工人 3 的两倍。它可能会触及,但效率低下。
对于 pmap
测试,我执行以下操作:
pmap(parallel_func, 1:12)
并得到输出:
From worker 2: job 1
From worker 3: job 2
From worker 2: job 3
From worker 2: job 5
From worker 3: job 4
From worker 2: job 6
From worker 2: job 8
From worker 3: job 7
From worker 2: job 9
From worker 2: job 11
From worker 3: job 10
From worker 2: job 12
现在,请注意,工人 2 执行了 8 个工作,工人 3 执行了 4 个工作。这与他们的速度和我们想要的最佳效率成正比。pmap
是一个艰巨的任务大师 - 从每个人的能力。