C Pthreads-高内存使用率

C Pthreads-高内存使用率,c,linux,multithreading,pthreads,memory-efficient,C,Linux,Multithreading,Pthreads,Memory Efficient,我正在用C语言编写一些东西,在256Mb系统上的Linux中创建很多pthread。我通常有+200Mb的空闲空间 当我用少量线程运行程序时,它可以工作,但一旦我让它创建大约100个线程,它就会出现错误,因为系统内存不足。我做了几个测试,每个线程使用了几乎2Mb的内存。线程的堆栈大小设置为16Kb 我用于创建每个线程的代码: pthread_attr_t attr; pthread_attr_init(&attr); size_t stacksize; stacksize = (doub

我正在用C语言编写一些东西,在256Mb系统上的Linux中创建很多pthread。我通常有+200Mb的空闲空间

当我用少量线程运行程序时,它可以工作,但一旦我让它创建大约100个线程,它就会出现错误,因为系统内存不足。我做了几个测试,每个线程使用了几乎2Mb的内存。线程的堆栈大小设置为16Kb

我用于创建每个线程的代码:

pthread_attr_t attr;
pthread_attr_init(&attr);
size_t stacksize;
stacksize = (double) 16*1024;
int res = pthread_attr_setstacksize (&attr, stacksize);
int res2 = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (res != 0 || res2 != 0) {
    logs << "pthread_attr_XX: error "+int2string(res);
    exit(-1);
}
pthread_t id;
pthread_create(&id, &attr, &Class::thread_callback, &some_var);
pthread\u attr\u t attr;
pthread_attr_init(&attr);
大小与堆叠大小;
stacksize=(双精度)16*1024;
int res=pthread_attr_setstacksize(&attr,stacksize);
int res2=pthread\u attr\u setdetachstate(&attr,pthread\u CREATE\u distached);
如果(res!=0 | | res2!=0){

logs是的,几乎任何操作系统都会在这么多线程上死机。这不是操作系统制造商(Linux或其他)非常关注的问题,因为很少有系统有这么多CPU,所以你的代码在100个线程上执行的速度可能不会比在8个线程上快很多(或无论您有多少个CPU)

我认为你需要做的是某种线程池。如果你真的需要那么多线程,我也怀疑本页上的ulimit答案会很有用,但正如我所说的,我认为在大多数情况下,很多线程并不能让你受益匪浅,如果你在程序中而不是在系统中修复它,它会使它更具可移植性。

为什么
stacksize=(双精度)16*1024;
?它是整数

尝试将其设置为32或64 KB,因为可能不允许使用16*1024;堆栈中也可能有TLS(即使您不使用TLS;库也可以,包括libc)

因此,将行更改为

stacksize = 64*1024; 

并检查内存消耗量。

< P>如果您想要更低的开销,请考虑用户空间线程技术,如光纤、ALA协作任务管理。

GNU可移植线程:

Boo+C++程序:

仅供参考的仅Windows光纤:


请参阅Wikipedia链接了解更多示例实现。

不确定它是否有用,但请尝试在创建第一个线程之前使用
RLIMIT_STACK
调用
setrlimit
,将堆栈大小限制为16k。

系统线程库的设计目的不是为了在内存非常有限的系统上支持大量线程y、 您需要使用为此目的而设计的线程库,或者使用更少的线程。这可能是原因:

“(认识到泄漏

如果您创建了一个可接合线程,但忘记加入它,那么它的资源或专用内存将始终保留在进程空间中,并且永远不会回收。请始终加入可接合线程;如果不加入它们,则可能会发生严重的内存泄漏。)”

请在这里阅读:

您确定您的系统内存不足,还是其他资源(可能是线程描述符)不足?@mah:线程描述符在Linux中不太可能,因为在后台,它们的处理方式与大多数事情的全过程一样,并从进程id池中提取,直到耗尽为止。更可能的是,内存问题是由堆上创建的东西和耗尽堆空间引起的。线程在做什么?您可能需要重新考虑在内存资源如此有限的机器上产生100个线程的设计。也许可以看看
select()
@mah,是的,我可以在其他终端中看到,使用的内存会不断增加,直到用完为止。是否使用了TLS(使用
\u thread
说明符的数组)?这也可能来自库。您的线程是否使用了大量来自malloc的内存?在res中是否真的没有返回错误?您的值正是最大的禁止值。检查是“
/*捕获无效大小。*/
\n
如果(stacksize
\n
返回EINVAL;
”16 kb可能太小了,所以也应该尝试
ulimit-s40
ulimit-s70
。@osgx:您建议的命令起到了作用,谢谢。我没有尝试使用setrlimit,但我想它也会起作用,因为它基于相同的设置。现在我可以打开许多内存使用率较低的线程。看起来pthread_attr_setstacksize是“无法按预期工作,需要更改全局限制。我认为问题不在于OP没有加入线程。问题与创建线程时使用的内存量有关。”。