如何在Python中使用多处理并行求和循环

use*_*101 7 python multiprocessing

我很难理解如何使用Python的多处理模块.

我有一个和1n哪里n=10^10,这是太大,无法进入名单,这似乎是在网上使用多很多例子推力.

有没有办法将范围"拆分"为一定大小的段,然后为每个段执行求和?

例如

def sum_nums(low,high):
    result = 0
    for i in range(low,high+1):
        result += i
    return result
Run Code Online (Sandbox Code Playgroud)

而且我想sum_nums(1,10**10)通过将其分解成许多来计算sum_nums(1,1000) + sum_nums(1001,2000) + sum_nums(2001,3000)...,等等.我知道有一个封闭形式,n(n+1)/2但假装我们不知道.

这是我尝试过的

import multiprocessing

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

if __name__ == "__main__":
    n = 1000 
    procs = 2 

    sizeSegment = n/procs

    jobs = []
    for i in range(0, procs):
        process = multiprocessing.Process(target=sum_nums, args=(i*sizeSegment+1, (i+1)*sizeSegment))
        jobs.append(process)

    for j in jobs:
        j.start()
    for j in jobs:
        j.join()

    #where is the result?
Run Code Online (Sandbox Code Playgroud)

bj0*_*bj0 1

首先,解决内存问题的最佳方法是使用迭代器/生成器而不是列表:

def sum_nums(low, high):
    result = 0
    for i in xrange(low, high+1):
        result += 1
    return result
Run Code Online (Sandbox Code Playgroud)

在 python3 中,range() 生成一个迭代器,因此仅在 python2 中需要它

现在,当您想要将处理拆分到不同的进程或 CPU 核心时,多处理就派上用场了。如果您不需要控制各个工作人员,那么最简单的方法是使用进程池。这将允许您将函数映射到池并获取输出。您也可以apply_async一次向池中申请一个作业,并获得延迟的结果,您可以通过以下方式获得.get()

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

# map requires a function to handle a single argument
def sn((low,high)):
    return sum_nums(low, high) 

if __name__ == '__main__': 
    #t = time()
    # takes forever   
    #print sum_nums(1,10**10)
    #print '{} s'.format(time() -t)
    p = Pool(4)

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

    # using apply_async
    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)

    # using process pool
    t = time()
    print sum(p.map(sn, zip([x+1 for x in r], r[1:])))
    print '{} s'.format(time() -t)
Run Code Online (Sandbox Code Playgroud)

在我的机器上,仅sum_nums使用 10**10 调用就需要将近 9 分钟,但使用Pool(8)andn=int(1e8)将其缩短到一分多钟。