【问题标题】:Python 2.7: "can't start new thread" error from "multiprocessing.Pool"Python 2.7:来自“multiprocessing.Pool”的“无法启动新线程”错误
【发布时间】:2015-12-12 07:15:23
【问题描述】:

这是我的情况。代码与example in the docs的代码几乎相同:

from multiprocessing import Pool
import numpy as np

def grad(x0, y): return 0 # does some computational-heavy work actually

if __name__ == '__main__':

    class UnrollArgs:
        def __init__(self, func):
            self.func = func

        def __call__(self, args):
            return self.func(*args)

    def batch_grad(x0, y, processes=4):
        g = Pool(processes).map(UnrollArgs(grad), [(x0, yi) for yi in y])
        return np.sum([gi for gi in g], axis=0) / len(y)

我传递给batch_grady 有50 个元素,Pool.map 抛出错误:

错误:无法启动新线程

从 Google 我知道这通常是由于一个人试图启动太多线程这一事实造成的。也许只有我一个人,但我认为multiprocessing.Pool 上的文档有点不完整。特别是,我不知道如何控制应该启动的线程数。 Pool 类的文档中甚至都没有提到“线程”一词。

multiprocessing.Pool 的完整参数是 number of processes to start,而不是线程。

那我该如何解决呢?

更新:值得注意的是,并不是每次运行代码时都会引发错误。

【问题讨论】:

  • 我在您发布的代码中看不到任何会导致该错误的内容。您可以发布一个更完整的示例(我可以运行的示例)吗?您是否在代码的其他地方使用了threading
  • @aganders3:这我的完整示例,only 例外,grad 正在做一些计算量很大的工作。该错误是从Pool 类的map 函数内部引发的。我使用threading
  • 如果您摆脱池并只使用map,它是否有效?使用您更正的代码,我无法在我的系统上重现此错误。
  • source 看来,在 Python 解释器启动期间,在 PyThread_start_new_thread(它是系统相关线程库的包装器)中创建线程似乎是一个低级故障。也许内存不足?
  • @theV0ID 我认为这个错误是在 Python 解释器本身的启动过程中产生的,当时multiprocessing 产生了多个解释器进程。在这种情况下,您无法控制解释器启动的实际线程数,至少不是multiprocessing。但我可能错了。我不是 CPython 内部的专家。

标签: python multithreading python-2.7 python-multiprocessing


【解决方案1】:

我认为问题源于产生了许多Pools。这个错误很奇怪,我认为@ChongMa 是正确的,它与 Python 解释器本身无法生成线程有关。听起来我在 cmets 中的建议可能对你有用,所以我在这里重新发布它作为答案。

尝试以下修复: a) 使用Pool.close() 方法让每个Pool 知道它不会再工作了:

def batch_grad(x0, y, processes=4):
    pool = Pool(processes)
    g = pool.map(UnrollArgs(grad), [(x0, yi) for yi in y])
    pool.close()
    return np.sum([gi for gi in g], axis=0) / len(y)

b) 重复使用 Pool 进行所有处理 - 将 Pool 对象传递给 batch_grad 函数,而不是多个进程:

def batch_grad(x0, y, pool=None):
    if pool is None:
        pool = Pool(4)
    g = pool.map(UnrollArgs(grad), [(x0, yi) for yi in y])
    return np.sum([gi for gi in g], axis=0) / len(y)

# then call your function like so
p = Pool(4)
batch_grad(your_x0, your_y, p)

希望这对你长期有效。

【讨论】:

  • 再次感谢,经过更多测试,我会“接受”您的回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-13
  • 2016-01-23
  • 1970-01-01
  • 2018-12-25
  • 1970-01-01
  • 2018-09-29
相关资源
最近更新 更多