2

我正在使用networkx(网络分析库)进行一些缓慢的计算,并且我正在尝试使用池工作人员来使其更快一些。计算是独立的,因此并行化它们应该相对简单。

def computeInfoPooled(G,num_list):
    pool=Pool(processes=4)

    def f(k):
        curr_stat={}
        curr_stat[k]=slow_function(k,G)
        return curr_stat

    result = pool.map(f,num_list)

    return result

现在,我在控制台中运行了以下命令:

computed_result=computeInfoPooled(G)

我希望这段代码创建 4 个进程,并在不同的进程中使用 num_list 的每个项目(一个数字)调用 f 。如果 num_list 包含超过 4 个数字(在我的情况下约为 300),它只会同时运行 4 个并将其余的排队,直到其中一个池工人完成。

当我运行我的代码时发生的事情是产生了许多 python.exe(或分叉,不确定发生了什么),并且似乎它正在创建无限多的进程,所以我不得不拔掉我的机器。

任何想法我做错了什么以及如何解决它?

4

2 回答 2

1

在 Windows 上,您需要

if __name__ == '__main__':
    computed_result = computeInfoPooled(G)

在不启动分叉炸弹的情况下使您的脚本可导入。(阅读文档中标题为“安全导入主模块”的部分。

另请注意,在 Windows 上,您可能无法使用交互式解释器中的多处理模块。请参阅文档顶部附近的警告:

此包中的功能要求子模块可以导入主模块。这在编程指南中有介绍,但值得在这里指出。这意味着某些示例,例如multiprocessing.Pool 示例将无法在交互式解释器中工作。(我的重点。)

相反,将脚本保存到文件中,例如script.py并从命令行运行它:

python script.py

此外,您需要参数是pool.map可腌制的。该函数f需要在模块级别定义(不是内部computeInfoPooled可picklable:

def f(k):
    curr_stat = slow_function(k, G)
    return k, curr_stat


def computeInfoPooled(G, num_list):
    pool = Pool(processes=4)
    result = pool.map(f, num_list)
    return dict(result)

if __name__ == '__main__':
    computed_result = computeInfoPooled(G)

顺便说一句,如果f返回一个字典,那么pool.map(f, ...)将返回一个字典列表。我不确定这是你想要的,特别是因为每个 dict 只有一个键值对。

相反,如果您让f返回一个 (key, value) 元组,那么pool.map(f, ...)将返回一个元组列表,然后您可以将其转换为带有dict(result).

于 2013-03-01T20:42:50.840 回答
0

这在 Programming Guidelines for Windows下的文档中进行了解释。

根据您的平台,每个进程可能必须启动一个全新的解释器和import您的模块才能f调用该函数。(在 Windows 上,它总是必须这样做。)当它import是你的模块时,所有顶级代码都会运行,其中包括行computed_result=computeInfoPooled(G),它创建了一个全新的 4 个进程池等。

您可以像处理任何其他情况一样解决这个问题,您希望同一文件既可作为模块导入又可作为脚本运行:

def computeInfoPooled(G,num_list):
    pool=Pool(processes=4)

    def f(k):
        curr_stat={}
        curr_stat[k]=slow_function(k,G)
        return curr_stat

    result = pool.map(f,num_list)

    return result

if __name__ == '__main__':
    computed_result=computeInfoPooled(G)

从您的编辑和评论来看,您似乎期望computeInfoPooled(G)从交互式解释器调用 to 将解决该问题。相同的链接文档部分详细解释了为什么它不起作用,简介顶部的一个重要说明直接说:

此包中的功能要求子模块可以导入主模块。这在编程指南中有介绍,但值得在这里指出。这意味着某些示例,例如 multiprocessing.Pool 示例将无法在交互式解释器中工作。

如果您想了解为什么这是真的,您需要阅读链接的文档(您还需要了解一点关于如何import工作pickle的知识multiprocessing)。

于 2013-03-01T20:38:54.287 回答