使用多个核心" blackbox"功能

时间:2015-02-18 23:14:56

标签: python multiprocessing scikit-learn

我们说我有一个" blackbox"具有如下设置的功能:

def bb_func():
    #Does lots of stuff
    #Including lots of scikit-learn stuff

if __name__ == '__main__':
    bb_func()

bb_func()显着占用CPU,并且可以从使用多个内核中获益。修改:我只需要运行bb_func() 一次

由于我使用scikit-learn,我想知道是否有可用的东西(不一定在包内)。

1 个答案:

答案 0 :(得分:2)

多次运行黑盒子的最简单方法是使用具有并行Pool功能的工作人员map。有几个python包具有map个函数。 multiprocessing是最流行的版本之一,内置于python标准库中。我使用一个名为pathos的包,它构建在multiprocessing接口上,并扩展它以通过套接字连接提供并行映射。 pathos还提供了更强大的并行map(我将在下面讨论)。在这里,我们看到几个并行映射,具有不同的风格(阻塞,异步和迭代)。

>>> def bb_func(id):
...   import random
...   import time
...   n = random.random()
...   time.sleep(n)
...   return int(10*n)
... 
>>> import pathos
>>> 
>>> thpool = pathos.multiprocessing.ThreadingPool()
>>> mppool = pathos.multiprocessing.ProcessingPool()
>>> pppool = pathos.pp.ParallelPythonPool()
>>> 
>>> # blocking map using multiple processes
>>> mppool.map(bb_func, range(10))
[4, 5, 8, 7, 4, 2, 0, 0, 5, 3]
>>>
>>> # iterative map using multiple threads
>>> res = thpool.imap(bb_func, range(10))
>>> res.next()
8
>>> res.next()
4
>>> list(res)
[8, 2, 5, 2, 4, 2, 3, 1]
>>>
>>> # asynchronous map able to work across sockets
>>> res = pppool.amap(bb_func, range(10))
>>> res.ready()
True
>>> res.get()
[1, 2, 8, 9, 6, 7, 0, 5, 8, 9]

使用pathos,也可以安排这些地图以提供分层并行性。在这里,我们以异步并行方式启动5个多处理映射, 每个多处理地图在10个项目上调用bb_func

>>> res = thpool.amap(mppool.map, [bb_func]*5, [range(10)]*5)
>>> res.get()
[[7, 1, 4, 7, 8, 9, 2, 6, 0, 2], [9, 5, 1, 6, 9, 0, 5, 3, 4, 5], [4, 7, 2, 7, 3, 5, 8, 3, 3, 9], [4, 8, 8, 8, 3, 5, 0, 6, 1, 0], [8, 0, 6, 7, 7, 4, 1, 6, 2, 7]]

pathos还提供了ssh tunnel连接的功能,因此如果您的套接字连接需要安全,则可以建立ssh tunnel并确保map发送通过隧道套接字的调用。此外,还有一个名为pyina的姊妹软件包,它使用map作为后端为MPI函数提供了类似的界面。如果您想使用MPI并计算群集调度程序而不是(或与pathos一致,我将让您看一下。 pyina使用mpi4py,并提供更直观的高级界面,用于执行利用MPI的并行批量调用。

bb_func会有两个关键问题。首先,bb_func需要是可序列化的。 pathos包(和pyina)使用dill序列化程序,因为dill可以序列化大多数python对象。如果要导入bb_func而不是在同一个文件(或解释器)中自己定义它,那么它更可能是可序列化的。其次,scikit-learn可以使用大量内存,因此并行运行多个scikit-learn调用通常会占用你所有的内存。至于如何解决这个内存限制...你需要尝试聪明地编写代码,并且可能使用诸如处理内存映射文件之类的技巧,或者在处理大型数据集(到文件或垃圾回收)之后立即处理他们已被使用。

在此处获取pathos(以及pyinadill):https://github.com/uqfoundation

编辑:我从您的编辑中看到,您只运行bb_func一次,而且它是一个黑盒子。所以在这种情况下的答案很容易......“不,抱歉。除非你想挖掘黑盒子,否则你会陷入困境。”