【问题标题】:Why threading.stack_size() does not produce the effect wanted?为什么 threading.stack_size() 没有产生想要的效果?
【发布时间】:2013-10-16 23:47:13
【问题描述】:

我在 Windows 7 x64 上使用 Python 2.7 x86。我现在想坚持使用 Python 2.7 for x86,因为我编写的应用程序将在大多数 x86 机器上使用。

现在,我正在编写的脚本在大约 700 个线程上运行良好。我正在使用队列。 出现了对更多线程的需求,所以很自然地,我只是增加了它们,但这并没有任何效果。脚本将因“无法启动新线程”异常而崩溃。

因此,在 * 上进行了大量挖掘之后,我发现了使用 threading.stack_size() 的想法,我还阅读了有关 python 的文档。 所以我继续这样做:

threading.stack_size(64*1024)

问题是,它没有效果。即使有足够的可用内存(接近 2.4GB),我仍然无法产生超过 700 个线程

为了更好地理解,这是代码的一部分。

class Downloader(threading.Thread):

    #----------------------------------------------------------------------
    def __init__(self, queue):
        threading.Thread.__init__(self)
        self.queue = queue

    #----------------------------------------------------------------------
    def run(self):
        while True:
            host,user,page= self.queue.get()
            self.checker(host,user,page)
            self.queue.task_done()
            threading.stack_size(64*1024)

经过数小时搜索该问题后,我找到的唯一解决方案是将 python 全部重新编译并编辑有关堆栈大小的部分。这个选项在我之上,我很确定我的问题还有另一个优雅的解决方案。

我检查了 Res Monitor,有大量可用的备用内存和空闲内存。 它只是拒绝通过 700 标记。 我使用 stack_size() 错误吗? 请不要建议我使用 Twisted / asyncore !

据我了解,这也与虚拟空间分配有关。考虑到有大量内存可供使用,任何可以帮助我增加线程数的机会/解决方案?

提前感谢您的帮助!

【问题讨论】:

  • 这里的问题不是将您限制为 700 个线程的设计,而是认为能够创建更多(甚至几乎那么多)将是有用的。
  • 这并没有真正解决我的问题,而且有点过分了。如果我不需要这么多,我就不会费心在这个问题上花费数小时和数天,不是吗?我并不是要不尊重他人,但我是来寻求帮助的,而不是为了重新设计代码。不过,我确实很欣赏这些提醒。
  • 我把它写成评论,而不是答案,原因很简单,它评论,而不是对您提出的问题的回答。老实说,我希望有人可以直接回答你的问题——但如果他们这样做了,我怀疑它真的有多大帮助。
  • @IchabodCrane:因为我真的怀疑你有一台运行 Python 的 700 核机器,所以你的大部分线程将按顺序执行,增加了持续上下文更改和 GIL 锁定/解锁/等待的开销(顺便说一句,除非你的代码是 IO 绑定的,否则它会自行杀死并行性)所以 Jerry Coffin 的观察是准确的。你很可能在一个失败的事业上浪费你的时间。这听起来很像 XY 问题,您应该解释一下您要解决的实际问题是什么,肯定有比使用 700 个线程更好的方法来解决它。

标签: c++ python multithreading networking


【解决方案1】:

你真的不需要那么多线程。我知道你相信你相信,但是 - 不,你不相信 ;-)

也就是说,您拨打stack_size() 的方式没有任何效果。您无法在创建线程之后更改堆栈大小,您必须在创建线程之前更改它之前。所以移动这个:

    threading.stack_size(64*1024)

到模块级别,只执行一次,并且在您创建任何线程之前。我不知道它是否会有所帮助,但这是正确的做法,而你这样做的方式是徒劳的。希望对您有所帮助!

【讨论】:

  • 其实这正是我所需要的。我做了修改,效果很好。非常感谢您的帮助!
  • 不客气!现在你应该解释你真正的问题,所以我们可以帮助你摆脱大约 690 个线程 ;-)
  • 客户端只是想要更多的电源如果脚本。这真的是唯一的问题,速度。而且我不知道如何比使用线程更好地做到这一点。我阅读了有关 asyncore / twisted 的信息,但我从未找到任何关于如何将它与采用 argv 并连接到大量套接字的函数一起使用的示例。