2

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

threading.stack_size(32768)

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

关于为什么它没有效果的任何想法?我真的在寻找解决方案,而不是评论我需要生成的线程数。

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

将不胜感激我能得到的任何帮助。

PS 请不要推荐使用 Twisted 或 Asyncore,我知道它们更好,但我需要根据当前情况充分利用它,而不是重新设计整个代码。

4

3 回答 3

4

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

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。

此外,CPythonthreading.stack_size在 Windows 上实现,因此它只控制最初提交的堆栈。它不会尝试控制堆栈的保留内存。从同一位置:

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

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

也就是说,即使您(您的线程)没有使用内存,并且即使您在系统上有更多的物理内存,Python 也无法使用其微小的 32 位指针来处理额外的内存,因此新线程超出了您的限制。重新遇到不能分配他们的保留内存(因为没有地址可以分配给它)。

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

也就是说,冒着让你对我大喊大叫的风险,我严重怀疑你需要的不仅仅是你已经可以创建的 1500 个线程。

于 2013-10-17T14:14:23.883 回答
1

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

于 2016-06-07T18:25:01.650 回答
0

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

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

于 2013-10-18T05:01:57.490 回答