如何使用C ++ 11 std :: thread设置stacksize

时间:2012-12-14 02:17:15

标签: c++ multithreading c++11 pthreads

我一直在努力熟悉C ++ 11中的 std :: thread 库,并且遇到了绊脚石。

最初我来自posix线程背景,并且想知道如何在构造之前设置std :: thread的堆栈大小,因为我似乎无法找到执行此类任务的任何引用。

使用pthreads设置堆栈大小是这样的:

void* foo(void* arg);
.
.
.
.
pthread_attr_t attribute;
pthread_t thread;

pthread_attr_init(&attribute);
pthread_attr_setstacksize(&attribute,1024);
pthread_create(&thread,&attribute,foo,0);
pthread_join(thread,0);

使用 std :: thread 时是否有类似内容?

我一直在使用以下参考资料:

http://en.cppreference.com/w/cpp/thread

6 个答案:

答案 0 :(得分:19)

  

最初我来自posix线程背景,并且想知道如何在构造之前设置std :: thread的堆栈大小,因为我似乎无法找到执行此类任务的任何引用。

你做不到。 std::thread不支持这一点,因为std::thread是标准化的,而C ++不要求机器甚至有堆栈,更不用说固定大小的堆栈。

pthreads在它们支持的硬件方面更具限制性,并且它假设每个线程有一些固定的堆栈大小。 (所以你可以配置它)

答案 1 :(得分:15)

正如Loki Astari所说,实际上需要一个非默认的堆栈大小并且通常是错误或编码错误的结果非常罕见。

  • 如果你觉得默认的堆栈大小对你的需求来说太大而想要减少它,那就别忘了。现在每个现代操作系统都使用虚拟内存/按需提交,这意味着只有在您访问页面之前,内存才会被保留,而不是实际分配。减少堆栈大小将减少实际内存占用量。

  • 由于这种行为,操作系统可以将默认堆栈大小设置为非常大的值。例如。在一个vanilla Debian上,这是8MB(ulimit -s),应该足以满足每个需求。如果你仍然设法达到这个限制,我的第一个想法是你的代码是错误的,所以你应该首先检查它并将事物移动到堆中,将递归函数转换为循环等等。

  • 如果尽管如此,确实需要更改堆栈大小(即增加它,因为减少它是无用的),在POSIX上你可以随时使用setrlimit在程序开始时增加默认堆栈大小。当然这会影响所有线程,但只有需要它的人才会实际使用额外的内存。

  • 最后但并非最不重要的是,平心而论,我可以看到减少堆栈大小的极端情况:如果你在32位系统上有大量线程,它们可能会占用你的虚拟地址空间(再次,而不是实际的内存消耗),直到您没有足够的可用于堆的地址空间。同样,setrlimit是你的朋友,即使我建议转移到64位系统以从更大的虚拟地址空间中受益(如果你的程序是那么大,你可能会受益于额外的RAM也是。)

答案 2 :(得分:15)

我一直在调查这个问题。对于某些应用程序,默认堆栈大小不足。示例:程序根据其正在解决的具体问题进行深度递归;程序需要创建许多线程并且内存消耗是一个问题。

以下是我发现的(部分)解决方案/解决方法的摘要:

  • g ++在Linux上支持-fsplit-stack选项。有关拆分堆栈的更多信息,请See。以下是他们网站的摘要:
  

拆分堆栈的目标是允许不连续的堆栈   根据需要自动增长。这意味着您可以运行多个   线程,每个都以一个小堆栈开始,并使堆栈增长   按程序要求缩小。

备注:-fsplit-stack仅在我开始使用gold linker后才对我有效。 看来clang ++也会支持这个标志。当我尝试使用标记-fsplit-stack编译我的应用程序时,我尝试的版本(clang ++ 3.3)崩溃了。

  • 在Linux上,通过在启动应用程序之前执行ulimit -s <size>来设置堆栈大小。 size是以Kbs为单位的堆栈大小。备注:命令unlimit -s unlimited不影响使用std::thread创建的线程的大小。当我使用ulimit -s unlimited时,主线程可能会增长,但使用std::thread创建的线程具有默认大小。

  • 在使用Visual Studio的Windows上,我们可以使用模块定义文件中的链接器/STACK参数或/STACKSIZE,这是所有创建的线程的默认大小。有关详细信息,请参阅this link。我们还可以使用命令行工具EDITBIN在任何可执行文件中修改此参数。

  • 在使用mingw g ++的Windows上,我们可以使用选项-Wl,--stack,<size>。出于某种原因,当使用cygwin g ++时,此标志仅影响主线程的大小。

的方法对我不起作用:

    OSX上的
  • ulimit -s <size>。它只影响主线程的大小。此外,pthread堆栈大小的Mac OSX默认值为512kB。

  • setrlimit仅影响Linux和OSX上主线程的大小。在cygwin上,它从来没有对我有用,似乎它总是会返回一个错误。

对于OSX,唯一的选择似乎是使用boost::thread而不是std::thread,但如果我们想要坚持使用标准,那就不好了。我希望g ++和clang ++将来也会在OSX上支持-fsplit-stack

答案 3 :(得分:14)

我在Scott Meyers的书Overview of the New C++(C++0x)中找到了这个,因为它很长,我不能发表评论,这有用吗?

  

还有一个用于获取特定平台的标准API   处理线程,互斥体,条件变量等。这些   假设句柄是设置线程优先级的机制,   设置堆栈大小等(关于设置堆栈大小,安东尼   威廉姆斯指出:“那些支持设置堆栈大小的操作系统,   他们都做得与众不同。如果您正在编写指定平台的代码   (这样使用native_handle就可以了),然后就可以使用了   该平台的设施可以切换堆栈。例如在POSIX你可以   使用makecontext和swapcontext以及a的显式分配   堆栈,在Windows上你可以使用Fibers。然后你可以使用   特定于平台的工具(例如链接器标志)来设置默认值   堆栈大小到很小的东西,然后切换到堆栈   在必要时更大的东西。“)

答案 4 :(得分:11)

我现在正在寻找答案。

看起来虽然std :: thread不支持这个,但是boost :: thread可以。

特别是,您可以使用boost::thread::attributes来完成此任务:

boost::thread::attributes attrs;
attrs.set_size(4096*10);
boost::thread myThread(attrs, fooFunction, 42);

答案 5 :(得分:1)

如果您不希望包含大型库,则可以进行类似的修改。

它仍然是依赖C ++编译器的STL库。 (现在是Clang / MSVC)

HackingSTL Library

std::thread thread = std::stacking_thread(65536, []{
    printf("Hello, world!\n"); 
});