4

我正在尝试实现多处理以加快复制循环,但无法使其在 Python27 中工作。这是我的程序的一个非常简化的版本,基于 SO 的文档和其他答案(例如Python multiprocessing pool.map for multiple arguments)。我意识到有很多关于多处理的问题,但到目前为止我还没有解决这个问题。希望我没有忽略任何太琐碎的事情。

代码

import itertools
from multiprocessing import Pool

def func(g, h, i):
    return g + h + i

def helper(args):
    args2 = args[0] + (args[1],)
    return func(*args2)

pool = Pool(processes=4)
result = pool.map(helper, itertools.izip(itertools.repeat((2, 3)), range(20)))
print result

这在使用时有效map(...),但在使用时无效pool.map(...)

错误信息:

Process PoolWorker-3:
Traceback (most recent call last):
File "C:\Program_\EPD_python27\lib\multiprocessing\process.py", line 258, in _
bootstrap
self.run()
File "C:\Program_\EPD_python27\lib\multiprocessing\process.py", line 114, in run
self._target(*self._args, **self._kwargs)
File "C:\Program_\EPD_python27\lib\multiprocessing\pool.py", line 85, in worker
task = get()
File "C:\Program_\EPD_python27\lib\multiprocessing\queues.py", line 376, in get
return recv()
AttributeError: 'module' object has no attribute 'helper'
4

3 回答 3

3

通过添加main()如下函数来解决问题:

import itertools
from multiprocessing import Pool

def func(g, h, i):
    return g + h + i

def helper(args):
    args2 = args[0] + (args[1],)
    return func(*args2)

def main():
    pool = Pool(processes=4)
    result = pool.map(helper,itertools.izip(itertools.repeat((2, 3)), range(10)))
    print result

if __name__ == '__main__':
    main()

根据@ErikAllik 的回答,我认为这可能是Windows 特有的问题。

编辑:这是关于python中的多处理的清晰且内容丰富的教程。

于 2013-10-02T10:28:49.100 回答
2

有一个multiprocessing称为pathos的分支(注意:使用 github 上的版本),它不需要starmap或 helpers 或所有其他东西——地图函数反映了 python 地图的 API,因此 map 可以接受多个参数。使用pathos,您通常也可以在解释器中进行多处理,而不是卡在__main__块中。pathos应该发布,经过一些温和的更新——主要是转换到 python 3.x。

  Python 2.7.5 (default, Sep 30 2013, 20:15:49) 
  [GCC 4.2.1 (Apple Inc. build 5566)] on darwin
  Type "help", "copyright", "credits" or "license" for more information.
  >>> from pathos.multiprocessing import ProcessingPool    
  >>> pool = ProcessingPool(nodes=4)
  >>>
  >>> def func(g,h,i):
  ...   return g+h+i
  ... 
  >>> p.map(func, [1,2,3],[4,5,6],[7,8,9])
  [12, 15, 18]
  >>>
  >>> # also can pickle stuff like lambdas 
  >>> result = pool.map(lambda x: x**2, range(10))
  >>> result
  [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
  >>>
  >>> # also does asynchronous map
  >>> result = pool.amap(pow, [1,2,3], [4,5,6])
  >>> result.get()
  [1, 32, 729]
  >>>
  >>> # or can return a map iterator
  >>> result = pool.imap(pow, [1,2,3], [4,5,6])
  >>> result
  <processing.pool.IMapIterator object at 0x110c2ffd0>
  >>> list(result)
  [1, 32, 729]
于 2014-01-20T20:42:51.347 回答
1

在我的 OS X 上,使用 Python 2.7,您的代码输出:

[5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]

我可以看到您的 Python 路径包含EPD_python27,所以也许可以尝试使用 vanila Python 发行版,而不是 Enthought Python 发行版。

更新:请参阅@fileunderwater 的答案以获得解决方案;我自己也遇到过这种情况,但完全忘记了:)

说明:问题发生(由于某种原因仅在 Windows 上,但也可能在 OS X 和 Linux 上发生)因为您的模块包含顶级代码。它的作用是在子流程中导入您multiprocessing的代码并执行它。但是,如果您的模块包含顶级代码,它将在模块被导入时立即评估/执行。将其包装起来main并仅有条件地调用main()(即使用if __name__ == '__main__'块),您可以防止这种情况发生。此外,这在 OS X 和 Linux 上更正确,并且通常比将代码直接放入模块中更可取。

于 2013-10-02T10:13:02.133 回答