Julia 1.5 中带有嵌套循环的并行赋值操作

Parallel assignment operations with nested loops in Julia 1.5

这与以下 post 密切相关,Przemyslaw Szufel 回答得很好。

考虑到我有一台 40 核的机器,我决定听从 Przemyslaw 的建议,使用 @distributed 而不是 Threads 来执行数组赋值操作。这很好地加快了速度。

我的算法与上述用户情况的唯一细微差别是我有嵌套 循环。当然,我总是可以向量化正在执行赋值操作的数组,但这会使我的代码复杂化。我是否应该简单地在最外层循环之前包含 @sync @distributed 并将其保留在那里?或者我是否需要在(在我的例子中是两个)内部循环之前放置额外的宏以最大化并行化的好处?

在分布式循环的情况下,您通常只想并行化最外层的循环。为什么?因为分布式工作负载需要大量时间。

但是,在某些情况下,您可能想要搜索不同的并行化策略。

让我们考虑一个执行时间不平衡的场景。 @distributed 采取了一种天真的方法,在工人之间平均分割循环。假设您有一个循环,例如:

for i in 1:100
    for j in 1:i
       ## do some heavy-lifting
    end
end

@distributed 放在外循环之前会非常低效,因为所有并行执行都将等待最后一个块,其中将处理 j 的所有最长值。这是一个典型的循环,其中并行化的价值将接近 non-existent。 在这种情况下,通常有以下方法:

  • 惰性方法:在内部循环上并行化。这在 i 的值比核心数
  • 大几个数量级的情况下会很好
  • 有效的方法。创建一个代理变量k in 1:(100*(100+1)/2),分配给它,然后计算ij
  • 的对应值

最后,如果作业时间严重不平衡并且上述方法不起作用,您需要使用一些作业轮询机制。一种方法是使用 asyncmap 生成远程任务,另一种方法是使用外部工具——我通常使用一些简单的 bash 脚本——我发布了使用 [=38 的方法=] 在 GitHub 上并行化作业:https://github.com/pszufe/KissCluster