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)
,分配给它,然后计算i
和j
的对应值
最后,如果作业时间严重不平衡并且上述方法不起作用,您需要使用一些作业轮询机制。一种方法是使用 asyncmap
生成远程任务,另一种方法是使用外部工具——我通常使用一些简单的 bash
脚本——我发布了使用 [=38 的方法=] 在 GitHub 上并行化作业:https://github.com/pszufe/KissCluster
这与以下 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)
,分配给它,然后计算i
和j
的对应值
最后,如果作业时间严重不平衡并且上述方法不起作用,您需要使用一些作业轮询机制。一种方法是使用 asyncmap
生成远程任务,另一种方法是使用外部工具——我通常使用一些简单的 bash
脚本——我发布了使用 [=38 的方法=] 在 GitHub 上并行化作业:https://github.com/pszufe/KissCluster