如何利用python多处理的所有核心

如何利用python多处理的所有核心,python,multiprocessing,Python,Multiprocessing,已经摆弄Python的多核函数一个多小时了,试图使用Process and Manager并行化一个相当复杂的图形遍历函数: 工作,但是,它是非常缓慢的!所以我假设我在工作中使用了错误的函数。希望这有助于澄清我到底想完成什么 EDIT2:。映射尝试: 工作,比单核慢。是时候优化了 这里堆积如山,无法在注释中解决,因此,mp是多处理: mp.cpu\u count应返回处理器的数量。但是要测试一下。有些平台很时髦,而且这些信息并不总是容易获得。Python尽了最大的努力 如果您启动24个进程,它们

已经摆弄Python的多核函数一个多小时了,试图使用Process and Manager并行化一个相当复杂的图形遍历函数:

工作,但是,它是非常缓慢的!所以我假设我在工作中使用了错误的函数。希望这有助于澄清我到底想完成什么

EDIT2:。映射尝试:


工作,比单核慢。是时候优化了

这里堆积如山,无法在注释中解决,因此,mp是多处理:

mp.cpu\u count应返回处理器的数量。但是要测试一下。有些平台很时髦,而且这些信息并不总是容易获得。Python尽了最大的努力

如果您启动24个进程,它们将完全按照您的要求执行;-看起来mp.Pool对你来说是最方便的。将要创建的进程数传递给其构造函数。mp.poolprocesss=None将使用mp.cpu\u计数表示处理器的数量

然后您可以使用,例如,.imap\u unordered。。。在池实例上,将您的degreelist分布到各个进程。或者也许其他一些池方法对你更有效——实验

如果您无法将问题转换到Pool的世界视图中,您可以创建一个mp.Queue来创建一个工作队列,.放置节点或节点片段,以减少主程序中的工作开销,并将工人写入。从该队列中获取工作项。询问是否需要示例。请注意,在所有实际工作项之后,您需要在队列中为每个进程设置一个sentinel值,以便工作进程可以测试sentinel以了解它们何时完成

仅供参考,我喜欢队列,因为它们更明确。很多人更喜欢游泳池,因为它们更神奇-

池示例 这里有一个可执行的原型。这显示了一种使用imap_无序池和chunksize的方法,不需要更改任何函数签名。当然,您必须插入真正的代码;-注意,init_worker方法允许每个处理器只传递一次大多数参数,而不是为degreeslist中的每个项目传递一次。减少进程间通信量对于提高速度至关重要

import multiprocessing as mp

def init_worker(mps, fps, cut):
    global memorizedPaths, filepaths, cutoff
    global DG

    print "process initializing", mp.current_process()
    memorizedPaths, filepaths, cutoff = mps, fps, cut
    DG = 1##nx.read_gml("KeggComplete.gml", relabel = True)

def work(item):
    _all_simple_paths_graph(DG, cutoff, item, memorizedPaths, filepaths)

def _all_simple_paths_graph(DG, cutoff, item, memorizedPaths, filepaths):
    pass # print "doing " + str(item)

if __name__ == "__main__":
    m = mp.Manager()
    memorizedPaths = m.dict()
    filepaths = m.dict()
    cutoff = 1 ##
    # use all available CPUs
    p = mp.Pool(initializer=init_worker, initargs=(memorizedPaths,
                                                   filepaths,
                                                   cutoff))
    degreelist = range(100000) ##
    for _ in p.imap_unordered(work, degreelist, chunksize=500):
        pass
    p.close()
    p.join()
我强烈建议按原样运行它,这样您就可以看到它的速度非常快。然后一次添加一点东西,看看这对时间有什么影响。例如,只需添加

   memorizedPaths[item] = item
对于所有的简单路径图来说,速度会大大减慢。为什么?因为dict随着每次添加而变得越来越大,并且这个过程安全dict必须在所有进程之间的隐蔽下同步。同步的单位是整个dict——mp机器无法利用内部结构对共享dict进行增量更新


如果你负担不起这笔费用,那么你就不能使用Manager.dict。聪明的机会比比皆是-

看起来很奇怪,您正在等待每个新进程结束test.join,然后循环开始另一个进程。在加入任何一个进程之前,尝试至少启动24个进程。是的,我只是在添加函数,看看什么是有效的…:有没有一种方法可以使计算机上的进程和处理器数量一样多?i、 是否有CPU的系统变量?而且如果我启动24个进程,它们是否会在清空时不断添加更多节点?我有4700个节点要排序!我想不会,这似乎是一厢情愿。有没有办法去做这样的事情?和R的MCLIVE类似,你也可以考虑。谢谢你的回复!我现在正在努力。Pool似乎不可行,因为我有5个参数,我不知道如何让它接受多个参数我正在使用pypy,pypy是Python2.7.3,所以没有星图,我不知道如何部分使用这么多参数!您可以为具有多个参数的.map或.Queue示例添加一个示例吗?添加了一个多处理代码段,该代码段我已经开始工作,但比单核运行时间慢得多。多个参数没有问题:传递一个元组。元组可以包含任意多的参数。嗯,我无法让它工作,你能提供一个映射函数的元组示例吗?我只想澄清语法,并找出问题是否出在别处!请参见编辑我的答案-有更简单的方法继续;-祝你好运
partialfunc = partial(_all_simple_paths_graph, DG=DG, cutoff=cutoff, memorizedPaths=memorizedPaths, filepaths=filepaths)
p = mp.Pool()
for item in processList:
    processVar = p.map(partialfunc, xrange(len(processList)))   
p.close()
p.join()
import multiprocessing as mp

def init_worker(mps, fps, cut):
    global memorizedPaths, filepaths, cutoff
    global DG

    print "process initializing", mp.current_process()
    memorizedPaths, filepaths, cutoff = mps, fps, cut
    DG = 1##nx.read_gml("KeggComplete.gml", relabel = True)

def work(item):
    _all_simple_paths_graph(DG, cutoff, item, memorizedPaths, filepaths)

def _all_simple_paths_graph(DG, cutoff, item, memorizedPaths, filepaths):
    pass # print "doing " + str(item)

if __name__ == "__main__":
    m = mp.Manager()
    memorizedPaths = m.dict()
    filepaths = m.dict()
    cutoff = 1 ##
    # use all available CPUs
    p = mp.Pool(initializer=init_worker, initargs=(memorizedPaths,
                                                   filepaths,
                                                   cutoff))
    degreelist = range(100000) ##
    for _ in p.imap_unordered(work, degreelist, chunksize=500):
        pass
    p.close()
    p.join()
   memorizedPaths[item] = item