5

我正在编写一些产生相当多线程的代码(目前大约有 512 个,但将来可能会更高)。每个线程只执行少量操作,因此我希望将线程置于系统上的开销保持在最低限度。

我正在使用 设置堆栈大小pthread_attr_setstacksize(),并且可以从中获得允许的最小堆栈大小PTHREAD_STACK_MIN。但我的问题是:使用PTHREAD_STACK_MIN线程堆栈大小是否安全?我该如何计算我需要多少堆栈?是否有任何隐藏的开销需要添加到我的计算中?

另外,我可以使用其他技术来减少线程对系统的负担吗?

4

3 回答 3

7

您不应该在这么多线程附近创建任何地方,而且您绝对不应该创建一个新线程来执行少量操作。当且仅当您现有的线程完全饱和并且有更多可用的物理或逻辑护理工作时,您才应该创建一个新线程。这将一个合理的当前应用程序硬限制在大约 10 个线程左右,即使您在六核上运行,您最多也只需要 12 个左右。这样的设计有很大的缺陷,会使用大量的进程内存,并且不会真正提高性能。

至于堆栈大小,您无法真正计算任意线程需要多少,因为它完全取决于代码运行。但是,在 Visual Studio 中,典型的堆栈大小为几兆字节。您必须发布整个代码以及线程执行的反汇编代码才能知道要使用多少堆栈大小。只需将其保持在几兆字节即可。

于 2010-11-11T12:59:47.427 回答
5

所需的堆栈帧大小取决于您使用的编译器,基本上您可以尝试猜测自动变量、参数的大小以及返回地址、保存寄存器等的一些开销。

您应该考虑是否可以替代使用Thread Pool。由于创建线程不是免费的。

于 2010-11-11T13:04:02.173 回答
4

减少线程堆栈大小不会减少开销(不是在 CPU、内存使用或性能方面)。您在这方面的唯一限制是为您的平台上的线程提供的总可用虚拟地址空间。

我会使用默认的堆栈大小,直到平台出现其他问题(如果它发生的话)。然后在出现问题时尽量减少堆栈使用。然而,这些将导致真正的性能问题,因为您需要占用堆,或在其他地方设计线程相关的分配

隐藏的间接费用可能包括:

  • 在堆栈上分配大型数组,例如通过VLA分配,alloca()或者只是简单的静态大小的自动数组。
  • 您无法控制或不知道使用模板、工厂类等的后果的代码。但是,鉴于您没有指定 C++,这不太可能成为问题。
  • 从库头文件等导入的代码。这些可能会在版本之间发生变化,并显着改变它们的堆栈,甚至线程使用。
  • 递归。这也是由于上述几点,请考虑诸如boost::bind可变参数模板,疯狂的宏,然后只是使用缓冲区或堆栈上的大对象的一般递归。

除了设置堆栈大小之外,您还可以根据需要操作线程优先级以及挂起和恢复它们,这将大大有助于调度程序和系统响应。Pthreads 允许您设置争用范围;LWP和范围内调度的性能特征差异很大。

以下是一些有用的链接:

于 2010-11-11T13:10:16.397 回答