Python threading.stack_size()无效

时间:2013-10-17 12:23:12

标签: python multithreading networking stack-size

我正在尝试减少python脚本的堆栈大小以生成更多线程。 我这样设置它

threading.stack_size(32768)

在任何线程开始之前将其置于导入级别 问题是,它没有效果。 无论有没有,我都可以开始确切的线程数。 我在Windows 7机器x64上使用Python 2.7 x86,超过2.4GB RAM。

有关它为何无效的任何想法? 我真的在寻找一个解决方案,而不是评论我需要产生的线程数。

我怀疑它与与线程相关的.pyc文件有关,我记得我遇到过这种情况,删除thoose .pyc文件并让python在下次运行时重新编译它们会应用更改,但我不知道是什么关于线程化的文件。

感谢我能得到的任何帮助。

P.S。请不要建议使用Twisted或Asyncore,我知道它们更好,但我需要在当前情况下充分利用它,而不是重新设计整个代码。

3 个答案:

答案 0 :(得分:2)

Windows上的最小线程堆栈大小可能至少为64kB。 Quoting

The operating system rounds up the specified size to the nearest multiple of the
system's allocation granularity (typically 64 KB). To retrieve the allocation
granularity of the current system, use the GetSystemInfo function.

因此尝试将其设置为32kB可能看起来很像将其设置为64kB。

此外,CPython在Windows上实现threading.stack_size,以便它只控制最初提交的堆栈。它不会尝试控制堆栈的保留内存。来自同一地点:

The reserved memory size represents the total stack allocation in virtual memory.

这意味着每个线程都会占用虚拟内存中的保留内存大小。您没有提到在遇到错误之前设置了多少线程,但我怀疑它只是在您的进程中耗尽可寻址内存(即使您正在运行,这可能是32位进程)它在Windows 7 x86-64上,因为CPython构建/分发是x86(-32))。

也就是说,即使你(你的线程)没有使用内存,即使系统上有更多的物理内存,Python也不能用它的32位地址额外的内存指针和超出你遇到的限制的新线程不能分配它们的保留内存(因为没有剩下的地址可以分配给它)。

如果您希望能够更改每线程保留内存,那么您可能需要以与CPython调用它不同的方式调用CreateThread_beginthreadex。这可能意味着需要更改CPython。

那就是说,并且冒着让你对我大喊大叫的风险,我严重怀疑你需要超过你已经创造的1500个线程。

答案 1 :(得分:0)

一种可能性是获得64位构建的python。那么你就不会遇到地址空间限制。您仍然会受到物理内存的限制,但这可能最终会成为一个不太重要的限制。如果您没有其他选择,它还可以让您选择购买更多内存。唯一的问题是,据我所知,许多第三方C扩展在Windows上不支持64位,或者至少默认情况下不提供64位版本。任何流行的64位Linux发行版默认使用64位python,所以如果你的软件没有绑定到Windows也可能是一个选项。如果你绝望,可以在Linux VM中运行你的应用程序。

我绝对可以理解不想使用像twisted这样的异步编程风格来重写代码。可能更可口的解决方案是使用像stackless python或eventlets这样的用户空间绿色线程系统。这将需要一些移植,但比切换到基于反应堆的方法要少得多。同样,它是否合适取决于您的申请。

答案 2 :(得分:0)

操作系统还可以限制您可以生成的线程/进程数。在Linux(Redhat)上,您可以使用ulimit -u进行检查。默认值为1024个进程/线程(内核将线程视为内部进程 - http://www.thegeekstuff.com/2013/11/linux-process-and-threads/)。这与其他ulimit值一起可以在/etc/security/limits.conf中设置。 我不确定Windows的等价物是什么,但这对于linux用户来说是一个解决方案,能够产生更多的线程/进程。