pmap
有一个batch_size
参数,默认为1。这意味着集合的每个元素都将逐一发送到可用的工作进程或任务中,由您提供的函数进行转换。如果每个函数调用执行大量的工作,并且每个调用所需的时间不同,使用pmap
的优点是不会让工人空闲,而其他工人在做工作,因为当一个工人完成一个转换时,它将要求处理下一个元素。因此,pmap
有效地在工作进程/任务之间“平衡负载”。
@distributed
循环,然而,最初会将给定范围的分区分配给工作进程,但并不知道每个分区需要多长时间。例如,考虑一个矩阵集合,其中前100个元素是2×2矩阵,接下来的100个元素是1000×1000矩阵,我们想使用@distributed
循环和2个工作进程来求每个矩阵的逆。
@sync @distributed for i = 1:200
B[i] = inv(A[i])
end
第一个工作进程将获取所有的2x2矩阵,第二个进程将获取1000x1000的矩阵。第一个进程会很快地完成所有的转换并空闲下来,而另一个进程将继续工作很长时间。虽然您使用了2个工作进程,但整个工作的主要部分将在第二个进程上有效地
串行执行,因此使用多个进程几乎不会带来任何好处。在并行计算环境中,这个问题被称为
负载平衡问题。即使要完成的工作是同构的,例如当一个处理器速度较慢而另一个处理器速度较快时,此问题也可能出现。
然而,对于非常小的工作转换,使用小批量大小的
pmap
会创建一些显著的通信开销,因为在每个批次之后,处理器需要从调用进程获取下一个批次,而使用
@distributed
for-loops,则每个工作进程将在开始时知道其所负责的范围。
选择
pmap
和
@distributed
for-loop取决于您的目标。如果您要像
map
那样转换一个集合,并且每个转换需要大量工作且该量不断变化,则您可能更喜欢选择
pmap
。如果每个转换非常微小,则您可能更喜欢选择
@distributed
for-loop。
请注意,如果在转换后需要进行约减操作,则
@distributed
for-loop已经提供了一个,大多数约减将在本地应用,而最终的约减将在调用进程上执行。但是,使用
pmap
,您需要自己处理约减。
如果确实需要一个非常复杂的负载平衡和约减方案,您也可以实现自己的
pmap
函数。
参考链接:
https://docs.julialang.org/en/v1/manual/parallel-computing/