如何使用C++11 std::thread设置堆叠大小
How to set the stacksize with C++11 std::thread
我一直在努力熟悉C++11中的std::thread库,但遇到了一个绊脚石。
起初,我来自posix线程背景,想知道如何在构建之前设置std::线程的堆栈大小,因为我似乎找不到任何执行此类任务的参考。
使用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
最初我来自posix线程背景,想知道如何在构建之前设置std::线程的堆栈大小,因为我似乎找不到任何执行此类任务的引用。
你不能。std::thread
不支持这一点,因为std::thread
是标准化的,C++甚至不要求机器有堆栈,更不用说固定大小的堆栈了。
pthreads在其支持的硬件方面更具限制性,并且它假设每个线程有一些固定的堆栈大小。(所以你可以配置这个)
正如Loki Astari已经说过的,实际需要非默认堆栈大小的情况极为罕见,通常是错误或错误编码的结果。
-
如果你觉得默认堆栈大小太大,无法满足你的需求,并想减少它,那就别想了。现在每个现代操作系统都使用虚拟内存/按需提交,这意味着在你访问页面之前,内存只是保留的,而不是实际分配的。减少堆栈大小将而不是减少实际内存占用。
-
由于这种行为,操作系统可以将默认堆栈大小设置为非常大的值。例如,在普通的Debian上,这是8MB(
ulimit -s
),应该足以满足所有需求。如果你仍然能够达到这个极限,我的第一个想法是你的代码是错误的,所以你应该首先审查它,并将其转移到堆中,将递归函数转换为循环,等等 -
尽管如此,如果确实需要更改堆栈大小(即增加堆栈大小,因为减少堆栈大小是无用的),那么在POSIX上,您可以在程序开始时使用setrlimit来增加默认堆栈大小。当然,这会影响所有线程,但只有那些需要它的线程才会实际使用额外的内存。
-
最后但同样重要的是,公平地说,我可以看到一个角落的情况,减少堆栈大小是有意义的:如果你在32位系统上有大量线程,它们可能会占用你的虚拟地址空间(同样,不是实际的内存消耗),直到你没有足够的地址空间用于堆。同样,setrlimit是你的朋友,尽管我建议你改用64位系统,以从更大的虚拟地址空间中受益(如果你的程序有那么大,你可能也会从额外的RAM中受益)。
我也一直在调查这个问题。对于某些应用程序,默认堆栈大小不够。示例:该程序根据所解决的特定问题进行深度递归;程序需要创建许多线程,内存消耗是个问题。
以下是我发现的(部分)解决方案/解决方案的摘要:
- g++支持Linux上的
-fsplit-stack
选项。有关拆分堆栈的详细信息,请参阅。以下是他们网站上的摘要:
拆分堆栈的目标是允许不连续的堆栈根据需要自动增长。这意味着您可以运行多个线程,每个线程从一个小堆栈开始,并使堆栈增长根据程序要求进行收缩。
备注:-fsplit-stack
只有在我开始使用黄金链接器后才对我有效。看来clang++也会支持这面旗帜。我尝试的版本(clang++3.3)在尝试使用标志-fsplit-stack
编译应用程序时崩溃。
-
在Linux上,在启动应用程序之前,通过执行
ulimit -s <size>
来设置堆栈大小。size
是以Kbs为单位的堆栈大小。备注:命令unlimit -s unlimited
不会影响使用std::thread
创建的线程的大小。当我使用ulimit -s unlimited
时,主线程可以增长,但使用std::thread
创建的线程具有默认大小。 -
在使用Visual Studio的Windows上,我们可以在模块定义文件中使用链接器
/STACK
参数或/STACKSIZE
,这是所有创建的线程的默认大小。有关详细信息,请参阅此链接。我们还可以使用命令行工具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
。
我在Scott Meyers的《Overview of the New C++(C++0x)
》一书中发现了这一点,因为时间很长,我无法将其作为评论发布,这有帮助吗?
还有一个标准的API用于获取特定于平台的线程、互斥对象、条件变量等后面的句柄句柄被假定为用于设置线程优先级的机制,设置堆栈大小等。(关于设置堆栈大小,AnthonyWilliams指出:"在那些支持设置堆栈大小的操作系统中,他们的做法各不相同。如果您正在为指定的平台进行编码(这样使用native_handle就可以了),然后可以使用该平台的交换堆栈设施。例如,在POSIX上,您可以使用makecontext和swapcontext以及显式分配堆栈,在Windows上可以使用Fibers。然后您可以使用用于设置默认值的特定于平台的设施(例如Linker标志)堆栈大小设置为非常小的值,然后将堆栈切换为在必要的地方更大的东西。")
刚才我自己也在寻找答案。
看起来std::thread不支持这个,boost::thread。
特别是,您可以使用boost::thread::attributes来实现这一点:
boost::thread::attributes attrs;
attrs.set_stack_size(4096*10);
boost::thread myThread(attrs, fooFunction, 42);
如果您不想包含一个大库,可以进行一些类似的修改。
它仍然依赖于C++编译器STL库。(Clang/MSVC现在)
破解STL库
std::thread thread = std::stacking_thread(65536, []{
printf("Hello, world!n");
});
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 在C++/Linux中设置单调时钟的一些技巧
- 如何在选项卡视图Qt中设置一个新项目,并保存以前的项目
- 嵌套在类中时无法设置成员数据
- 需要帮助设置在C++中使用的Potrace
- 如何在自删除后将对象设置为nullptr
- 将指针设置为"nullptr"并不能防止双重删除?
- 如何在Ubuntu中使用cmake设置qt4
- ld:bind_at_load和-bitcode_bundle(Xcode设置ENABLE_bitcode=YES)不能
- 如何在boost beast http请求中设置http头
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 如何将这个C++哈希表转换为动态扩展和收缩,而不是使用硬设置的最大值
- 为什么文件名被设置为一个点,而不是在读取矢量中的文件名时
- 如何在24位SDL_Surface上设置像素的颜色
- std::设置自定义比较器
- 如何设置一个范围来提取我想要获得的信息
- 如何在C/C++中用FD_set Unix设置套接字文件描述符
- 在std::thread中,joinable()然后join()线程安全吗
- 通过选项卡的文本设置QTabWidget顺序
- 如何使用C++11 std::thread设置堆叠大小