Python中的并行处理

38 投票
4 回答
30911 浏览
提问于 2025-04-16 04:51

有没有什么简单的代码可以在Python 2.7中实现并行处理?我在网上找到的例子都很复杂,还包含一些不必要的代码。

我想写一个简单的暴力整数因式分解程序,能在每个核心上处理一个整数(我有4个核心)。其实我的程序可能只需要2个核心,并且需要共享一些信息。

我知道有parallel-python和其他库,但我想尽量少用库,所以我想用Python自带的thread和/或multiprocessing库。

4 个回答

1

我同意,如果你想在标准库里工作,使用 Pool 这个来自 multiprocessing 的工具可能是最好的选择。如果你想尝试其他类型的并行处理,但又不想学习新的东西(也就是说,还是想用和 multiprocessing 一样的操作方式),那么你可以试试 pathos。它提供了几种并行处理的方式,使用起来和 multiprocessing 基本一样。

Python 2.7.6 (default, Nov 12 2013, 13:26:39) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy
>>> numToFactor = 976
>>> def isFactor(x):
...   result = None
...   div = (numToFactor / x)
...   if div*x == numToFactor:
...     result = (x,div)
...   return result
... 
>>> from pathos.multiprocessing import ProcessingPool as MPool
>>> p = MPool(4)
>>> possible = range(1,int(numpy.floor(numpy.sqrt(numToFactor)))+1)
>>> # standard blocking map
>>> result = [x for x in p.map(isFactor, possible) if x is not None]
>>> print result
[(1, 976), (2, 488), (4, 244), (8, 122), (16, 61)]
>>>
>>> # asynchronous map (there's also iterative maps too)
>>> obj = p.amap(isFactor, possible)                  
>>> obj
<processing.pool.MapResult object at 0x108efc450>
>>> print [x for x in obj.get() if x is not None]
[(1, 976), (2, 488), (4, 244), (8, 122), (16, 61)]
>>>
>>> # there's also parallel-python maps (blocking, iterative, and async) 
>>> from pathos.pp import ParallelPythonPool as PPool
>>> q = PPool(4)
>>> result = [x for x in q.map(isFactor, possible) if x is not None]
>>> print result
[(1, 976), (2, 488), (4, 244), (8, 122), (16, 61)]

另外,pathos 还有一个姐妹包,叫 pyina,它使用 mpi4py,但提供了在 MPI 中运行的并行处理方式,并且可以用多种调度器来运行。

还有一个好处是,pathos 提供了比标准 Python 更强大的序列化工具,这让它在处理各种函数和其他东西时,比 multiprocessing 更有能力。而且你可以直接在解释器中完成所有操作。

>>> class Foo(object):
...   b = 1
...   def factory(self, a):
...     def _square(x):
...       return a*x**2 + self.b
...     return _square
... 
>>> f = Foo()
>>> f.b = 100
>>> g = f.factory(-1)
>>> p.map(g, range(10))
[100, 99, 96, 91, 84, 75, 64, 51, 36, 19]
>>> 

你可以在这里获取代码:https://github.com/uqfoundation

8

mincemeat 是我找到的最简单的地图/减少(map/reduce)实现方式。而且,它对其他库的依赖非常少——它只需要一个文件,就能用标准库完成所有功能。

32

在Python中,开始学习并行处理的一个简单方法就是使用多进程中的池映射。这就像普通的Python映射,但每个函数调用会分散到不同的进程中去执行。

分解因数是一个很好的例子,你可以通过暴力检查所有的除法,把任务分散到所有可用的进程上:

from multiprocessing import Pool
import numpy

numToFactor = 976

def isFactor(x):
    result = None
    div = (numToFactor / x)
    if div*x == numToFactor:
        result = (x,div)
    return result

if __name__ == '__main__':
    pool = Pool(processes=4)
    possibleFactors = range(1,int(numpy.floor(numpy.sqrt(numToFactor)))+1)
    print 'Checking ', possibleFactors
    result = pool.map(isFactor, possibleFactors)
    cleaned = [x for x in result if not x is None]
    print 'Factors are', cleaned

这样我就得到了

Checking  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
Factors are [(1, 976), (2, 488), (4, 244), (8, 122), (16, 61)]

撰写回答