首页 > 解决方案 > Python:在 4 个内核上划分的相同工作负载适用于多处理库,但在使用 mpi4py 时会挂起

问题描述

我正在尝试了解有关使用 Python 进行多处理的更多信息。到目前为止,我已经使用了多处理库和 mpi4py 库,试图解决一个相当简单的问题。添加大量数字。

我使用以下逻辑,目标是将所有数字相加到 10^8,所以我将此范围划分为 4(我的笔记本电脑拥有的内核数)相等的范围,将负载分配到所有内核,然后将结果加在一起一个核心。

到目前为止,我有两种不同的方法。

使用多处理库:

import multiprocessing
from multiprocessing import Pool
from time import time

def sum_nums(low, high):
    result = 0
    for i in xrange(low, high+1):
        result += i
    return result

def sn((low,high)):
    return sum_nums(low, high) 

if __name__ == '__main__': 

    p = Pool(4)

    n = int(1e8)
    r = range(0,10**8+1,n)
    results = []

    t = time()
    for arg in zip([x+1 for x in r],r[1:]):
        results.append(p.apply_async(sum_nums, arg))

    # wait for results
    print sum(res.get() for res in results)
    print '{} s'.format(time() -t)

使用 mpi4py 库:

from mpi4py import MPI
import numpy as np
import time

comm = MPI.COMM_WORLD
size = comm.Get_size()
rank = comm.Get_rank()

if rank == 0:
    end = 10**9
    step = round((end+1)/size)
    limits = np.linspace(start=0, stop=end,num=size+1, 
endpoint=True, dtype=int)
    space = []
    for arg in zip([x+1 for x in limits],limits[1:]):
        space.append(arg)
else:
    space = None

data = comm.scatter(space, root=0)
start = time.time()
res = np.sum(np.arange(start=data[0], stop=data[1]+1))

timeDiff = time.time() - start
results = comm.gather(res, root=0)
totalTime = comm.gather(timeDiff, root=0)
if rank == 0:
    end = time.time()
    print(sum(results))
    print("Average computing time: {:.3f}s".format(sum(totalTime)/size))

问题是,虽然 mpi4py 库运行得更快,但尝试计算总和到 10^7 需要接近 1 秒,而使用第一个代码则需要 4。当尝试求解 10^8 时第二个代码挂起,而第一个代码在大约 15 秒内给出结果。

为什么会这样?是内存问题吗?我在第二个代码中得到了完全错误的东西吗?

第一个代码是用 python 2.7.15 编写的,第二个代码是用 python 3.6.7 编写的。

感谢您花时间阅读本文,欢迎任何回答!

标签: pythonmultiprocessingmpi

解决方案


我相信这是一个内存问题。我已经在我的 python 3.6.7 环境中尝试了第二个代码。当 end<=10^9 时,该代码在我的计算机上运行。我的电脑需要超过 40GB 的内存,最终达到 10^10。


推荐阅读