多处理池映射运行python模拟的Monte Carlo集合速度非常慢

2024-05-13 20:46:06 发布

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

我有一个python代码,它为一组参数运行2D扩散模拟。我需要多次运行代码,O(1000),就像蒙特卡罗方法一样,每次使用不同的参数设置。为了更快地完成这项工作,我希望使用机器(或集群)上的所有内核,以便每个内核运行一个代码实例

在过去,我为串行fortran代码成功地完成了这项工作,编写了一个python包装器,然后使用多处理映射(或者在多个参数的情况下使用starmap)在模拟集合中调用fortan代码。它工作得非常好,您可以循环1000个模拟,python包装器在完成以前的集成后,一旦释放,就会将一个新的集成分发到一个核心

然而,现在当我将其设置为运行python(而不是fortran)代码的多个实例时,我发现它的速度非常慢,比在单个内核上串行运行代码1000次要慢得多。使用系统监视器,我看到一次只有一个内核在工作,而且它的负载永远不会超过10-20%,而我当然希望看到N个内核在接近100%的情况下运行(就像我将fortran作业分包出去时一样)

我认为这可能是一个写入问题,因此我仔细检查了代码,以确保所有打印都已关闭,事实上根本没有文件/磁盘访问,现在我只在最后有一条打印语句来打印最终诊断

我的代码结构如下

我在toy\u diffusion\u 2d.py中有主要的python代码,其中有一个字典的参数,其中包含运行参数:

def main(arg)
loop over timesteps:
    calculation simulation over a large-grid
print the result statistic

然后我编写了一个“包装器”脚本,在这里我导入主要的模拟代码并尝试并行运行:

from multiprocessing import Pool,cpu_count
import toy_diffusion_2d

# dummy list of arguments
par1=[1,2,3]
par2=[4,5,6]

# make a list of dictionaries to loop over, 3x3=9 simulations in all.
arglist=[{"par1":p1,"par2":p2} for p1 in par1 for p2 in par2] 

ncore=min(len(arglist),int(cpu_count()))
with Pool(processes=ncore) as p:
    p.map(toy_diffusion_2d.main,arglist)

以上是一个较短的释义示例,我的实际代码较长,因此我将它们放在这里:

主代码:http://clima-dods.ictp.it/Users/tompkins/files/toy_diffusion_2d.py

您可以使用以下默认值运行此操作:

python3 toy_diffusion_2d.py

包装器脚本:http://clima-dods.ictp.it/Users/tompkins/files/toy_diffusion_loop.py

您可以运行这样的4人合奏:

python3 toy_diffusion_loop.py --diffK=[33000,37500] --tau_sub=[20,30]

(请注意,每次运行的最终统计值略有不同,即使与模型随机值相同,这是一个随机allen-cahn方程的版本,以防任何人感兴趣,但在扩散项上使用了一个愚蠢的显式解算器)

正如我所说,第二个并行代码可以工作,但正如我所说,它确实很慢。。。就像它一直在关着门

我也尝试过使用starmap,但没有什么不同,它几乎就像桌面一次只允许运行一个python解释器一样。。。?我花了几个小时在上面,我几乎要用Fortran重写代码了。我肯定我只是在做一些非常愚蠢的事情来阻止并行执行

编辑(1):此问题发生在 4.15.0-112-通用x86_64 GNU/Linux,带Python 3.6.9

作为对评论的回应,事实上我也发现它在我的MAC笔记本电脑上运行良好

编辑(2):看来我的问题有点重复了其他几个帖子,抱歉!除了Pavel提供的有用链接外,我还发现这个页面非常有用:Importing scipy breaks multiprocessing support in Python我将在下面的解决方案中编辑接受的答案


Tags: 实例代码inpyloop编辑参数内核
1条回答
网友
1楼 · 发布于 2024-05-13 20:46:06

您提供的代码示例在我的MacOS Catalina 10.15.6上运行良好。我猜您正在使用一些Linux分布式,根据this answer,可能是numpy导入由于与OpenBLAS库链接而影响了核心亲和力

如果您的Unix支持调度程序接口,则某些like this将起作用:

>>> import os
>>> os.sched_setaffinity(0, set(range(cpu_count)))

对这个问题有很好解释的另一个问题is found here和建议的解决方案是:

os.system('taskset -cp 0-%d %s' % (ncore, os.getpid()))

在多处理调用之前插入

相关问题 更多 >