并行python还是MPI?

2024-05-20 13:37:01 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个繁重的符号计算代码(许多多重符号积分)。此外,我还可以访问一台8核cpu计算机(带18 GB RAM)和一个32 cpu的小型集群。我宁愿留在我教授的8核个人电脑上,也不愿在有限的时间内使用他的集群去另一个教授的实验室,但是,我不确定它是否适用于SMP系统,所以我在Python中寻找一个并行工具,它可以同时用于SMPClusters上,当然,我更希望一个系统上的代码能够轻松地并且不费吹灰之力就可以在另一个系统上修改。

到目前为止,我发现Parallel Python(PP)非常适合我的需要,但我最近告诉过MPI也有同样的功能(pyMPI或MPI4py)。我不能同意这一点,因为似乎很少有人在网上讨论这个问题,只有here有人说,MPI(pyMPI或MPI4py)只适用于集群,如果我说得对的话!

“并行Python”是我唯一的选择,还是我还可以很高兴地使用基于MPI的解决方案?哪一个更适合我的需要?

PS。他们似乎都没有非常全面的文件,所以如果你知道一些链接,除了他们的官方网站,可以帮助一个新手并行计算,我将非常感谢,如果你也提到你的答案:)


编辑

我的代码有两个循环,一个在另一个内部,不能并行化外部循环,因为它是一个迭代方法(递归解),每个步骤都取决于在前一步中计算的值。外环包含内环以及3个附加方程其计算依赖于内环的整个结果。然而,内环(包含12个可在每一步计算的方程中的9个)可以安全地并行化,所有3*3个方程彼此独立w.r.t,仅取决于前一步。我所有的方程计算量都很大,因为每个方程都包含许多多重符号积分。似乎我可以分别并行化这9个方程中的内环的9个方程和积分计算,也可以并行化内环旁边3个方程中的所有积分。你可以找到我的代码here如果它能帮助你更好地理解我的需要,它是在SageMath内部编写的。


Tags: 代码here系统计算机符号集群mpi4pycpu
3条回答

我最近遇到了一个类似的问题。但是,以下解决方案仅在以下情况下有效:(1)希望在一组文件上单独运行python脚本,(2)脚本的每个调用都独立于其他调用。

如果上述方法适用于您,最简单的解决方案是在bash中按照以下行编写一个包装器:

for a_file in $list_of_files
do
    python python_script.py a_file &
done

“&;”将作为子进程运行前面的命令。其优点是bash不会等到python脚本完成后再继续for循环。

您可能希望限制同时运行的进程数,因为此代码将使用所有可用资源。

我将关注multiprocessing(doc),它提供了一系列很好的工具来生成和处理子进程。

引用文档:

multiprocessing is a package that supports spawning processes using an API similar to the threading module. The multiprocessing package offers both local and remote concurrency, effectively side-stepping the Global Interpreter Lock by using subprocesses instead of threads.

从评论中我认为Pool和它的map可以满足您的目的(doc)

def work_done_in_inner_loop(arg):
    # put your work code here
    pass

p = Pool(9)
for o in outer_loop:
     # what ever else you do
     list_of_args = [...] # what your inner loop currently loops over
     res = p.map(work_done_in_inner_loop,list_of_args])
     # rest of code

似乎有一些合理的方法来设计这个。

让我把你的工作称为主要工作,9个中间工作,以及中间工作可以衍生的许多内部工作。我假设中间作业在内部作业全部完成后有一个“合并”步骤,而外部作业也一样。

最简单的设计是,主作业触发中间作业,然后在执行合并步骤之前等待它们全部完成。然后,中间作业将触发内部作业,并在执行合并步骤之前等待它们全部完成。

这可以使用单个共享队列,但您需要一个队列,该队列在等待时不会阻塞工作池,而且我认为multiprocessingPoolQueue不能在开箱即用的情况下做到这一点。一旦你的所有进程都在等待加入他们的孩子,什么也做不了。

一种方法是改为连续传递样式。如果您知道哪个中间作业将最后完成,则可以将句柄传递给其他中间作业,并让它在这些作业上联接,然后执行合并,而不是外部作业。中间层同样将合并传递到他们的最后一个内部作业。

问题是,即使没有日程安排问题,你通常也无法知道最后要完成什么。因此,这意味着您需要某种形式的共享(例如,信号量)或作业之间的消息传递,以便在它们之间进行协商。你可以在multiprocessing上面做。唯一的问题是它破坏了作业的独立性,而且您突然要处理共享并发的所有恼人问题。

另一种选择是为每个中间作业分别设置池和队列,并在池之间进行某种负载平衡,以确保每个核心运行一个活动进程。

当然,也可以是一个单独的池,它的实现比multiprocessing的要复杂得多,它既可以进行负载平衡,也可以进行协作调度,因此joiner不会阻塞核心。

或者一个超级简单的解决方案:超额调度,并且为简单起见在上下文切换中支付一点成本。例如,即使只有8个内核,也可以运行32个工作线程,因此有22个活动工作线程和10个等待线程。每个核心都有2或3个活动的worker,这会使事情慢一点,但可能不会太糟,至少没有人空闲,除了向multiprocessing.Pool构造函数传递不同的参数之外,您不必编写任何代码。

无论如何,multiprocessing是非常简单的,它几乎没有不适用于其他解决方案的额外概念。所以,在你碰到砖墙或者没有碰到砖墙之前,花在玩它上面的时间可能比事先想清楚它是否对你有用要少。

相关问题 更多 >