Python:多处理,悲伤等等
Python: multiprocessing, pathos and what not
我必须提前道歉,因为这个问题很笼统,可能不够清楚。问题是:你如何 运行 并行一个 Python 函数,它本身使用一个进程池来处理某些子任务并执行大量繁重的 I/O 操作?它甚至是一个有效的任务吗?
我会尝试提供更多信息。我有一个程序,比如 test_reduce()
,我需要并行 运行。我尝试了几种方法来做到这一点(见下文),但我似乎缺乏一些知识来理解为什么它们都失败了。
这个 test_reduce()
过程做 很多 的事情。其中一些比其他问题更相关(我在下面列出):
- 它使用
multiprocessing
模块 (原文如此!),即 pool.Pool
实例,
- 它使用 MongoDB 连接,
- 它严重依赖
numpy
和 scikit-learn
库,
- 它使用回调和 lambda,
- 它使用
dill
库来腌制一些东西。
首先我尝试使用一个multiprocessing.dummy.Pool
(这似乎是一个线程池)。不知道这个pool具体是什么,为什么会这样,呃,"dummy";整个过程成功了,我得到了结果。 问题 是CPU 负载。对于 test_reduce()
的并行部分,所有核心都是 100%;对于同步部分,大部分时间约为 40-50%。我不能说这种 "parallel" 执行的总体速度有任何提高。
然后我尝试使用一个multiprocessing.pool.Pool
实例来map
这个程序到我的数据。失败并显示以下内容:
File "/usr/lib/python2.7/multiprocessing/pool.py", line 251, in map
return self.map_async(func, iterable, chunksize).get()
File "/usr/lib/python2.7/multiprocessing/pool.py", line 558, in get
raise self._value
cPickle.PicklingError: Can't pickle <type 'thread.lock'>: attribute lookup thread.lock failed
我猜测 cPickle
是罪魁祸首,并发现 pathos
库使用了更高级的 pickler dill
。但是它也失败了:
File "/local/lib/python2.7/site-packages/dill/dill.py", line 199, in load
obj = pik.load()
File "/usr/lib/python2.7/pickle.py", line 858, in load
dispatch[key](self)
File "/usr/lib/python2.7/pickle.py", line 1083, in load_newobj
obj = cls.__new__(cls, *args)
TypeError: object.__new__(generator) is not safe, use generator.__new__()
现在,这个错误是我完全不明白的。当我的过程在池中工作时,我的过程没有输出到 stdout
,所以很难猜测发生了什么。我唯一知道的是 test_reduce()
运行 在不使用多处理时成功。
那么,您如何 运行 并行处理如此繁重复杂的内容?
因此,感谢@MikeMcKerns 的回答,我找到了如何使用 pathos
库完成工作。我需要摆脱所有 pymongo
游标,它们(作为生成器)不能被 dill
腌制;这样做解决了问题,我设法并行 运行 我的代码。
我必须提前道歉,因为这个问题很笼统,可能不够清楚。问题是:你如何 运行 并行一个 Python 函数,它本身使用一个进程池来处理某些子任务并执行大量繁重的 I/O 操作?它甚至是一个有效的任务吗?
我会尝试提供更多信息。我有一个程序,比如 test_reduce()
,我需要并行 运行。我尝试了几种方法来做到这一点(见下文),但我似乎缺乏一些知识来理解为什么它们都失败了。
这个 test_reduce()
过程做 很多 的事情。其中一些比其他问题更相关(我在下面列出):
- 它使用
multiprocessing
模块 (原文如此!),即pool.Pool
实例, - 它使用 MongoDB 连接,
- 它严重依赖
numpy
和scikit-learn
库, - 它使用回调和 lambda,
- 它使用
dill
库来腌制一些东西。
首先我尝试使用一个multiprocessing.dummy.Pool
(这似乎是一个线程池)。不知道这个pool具体是什么,为什么会这样,呃,"dummy";整个过程成功了,我得到了结果。 问题 是CPU 负载。对于 test_reduce()
的并行部分,所有核心都是 100%;对于同步部分,大部分时间约为 40-50%。我不能说这种 "parallel" 执行的总体速度有任何提高。
然后我尝试使用一个multiprocessing.pool.Pool
实例来map
这个程序到我的数据。失败并显示以下内容:
File "/usr/lib/python2.7/multiprocessing/pool.py", line 251, in map
return self.map_async(func, iterable, chunksize).get()
File "/usr/lib/python2.7/multiprocessing/pool.py", line 558, in get
raise self._value
cPickle.PicklingError: Can't pickle <type 'thread.lock'>: attribute lookup thread.lock failed
我猜测 cPickle
是罪魁祸首,并发现 pathos
库使用了更高级的 pickler dill
。但是它也失败了:
File "/local/lib/python2.7/site-packages/dill/dill.py", line 199, in load
obj = pik.load()
File "/usr/lib/python2.7/pickle.py", line 858, in load
dispatch[key](self)
File "/usr/lib/python2.7/pickle.py", line 1083, in load_newobj
obj = cls.__new__(cls, *args)
TypeError: object.__new__(generator) is not safe, use generator.__new__()
现在,这个错误是我完全不明白的。当我的过程在池中工作时,我的过程没有输出到 stdout
,所以很难猜测发生了什么。我唯一知道的是 test_reduce()
运行 在不使用多处理时成功。
那么,您如何 运行 并行处理如此繁重复杂的内容?
因此,感谢@MikeMcKerns 的回答,我找到了如何使用 pathos
库完成工作。我需要摆脱所有 pymongo
游标,它们(作为生成器)不能被 dill
腌制;这样做解决了问题,我设法并行 运行 我的代码。