linux中每个进程的最大线程数

时间:2011-04-12 12:43:41

标签: linux pthreads

我编写了一个简单的程序来计算进程在linux(Centos 5)中可以拥有的最大线程数。这是代码:

int main()
{
    pthread_t thrd[400];
    for(int i=0;i<400;i++)
    {
        int err=pthread_create(&thrd[i],NULL,thread,(void*)i);
        if(err!=0)
            cout << "thread creation failed: " << i <<" error code: " << err << endl;
    }
    return 0;
}

void * thread(void* i)
{
    sleep(100);//make the thread still alive
    return 0;
}

我发现线程的最大数量只有300!如果我还需要更多,该怎么办? 我必须提到pthread_create返回12作为错误代码。

之前谢谢

5 个答案:

答案 0 :(得分:17)

Linux的线程限制,可以通过将所需的限制写入/proc/sys/kernel/threads-max来修改运行时。默认值从可用系统内存计算。除了该限制之外,还有另一个限制:/proc/sys/vm/max_map_count限制了最大mmapped段,并且至少最近的内核将为每个线程mmap内存。如果你点击它会增加这个限制应该是安全的。

在32位操作系统中,你所遇到的限制是缺少虚拟内存。如果你的硬件支持它,安装64位Linux,你会没事的。我可以轻松启动30000个堆栈大小为8MB的线程。该系统有一个Core 2 Duo + 8 GB的系统内存(我在同一时间使用5 GB用于其他内容)并且它运行64位Ubuntu和内核2.6.32。请注意,必须允许内存过量使用(/ proc / sys / vm / overcommit_memory),否则系统将需要至少240 GB的可提交内存(实际内存和交换空间的总和)。

如果您需要大量线程且无法使用64位系统,您唯一的选择是最小化每个线程的内存使用量以节省虚拟内存。首先请求尽可能少的堆栈。

答案 1 :(得分:6)

您的系统限制可能不允许您映射所需的所有线程的堆栈。查看/proc/sys/vm/max_map_count,然后查看this answer。我不是100%确定这是你的问题,因为大多数人在much larger thread counts遇到问题。

答案 2 :(得分:4)

当我的线程数超过某个阈值时,我也遇到了同样的问题。 这是因为/etc/security/limits.conf中的用户级别限制(用户可以一次运行的进程数)设置为1024。

请检查您的/etc/security/limits.conf并查找条目: -

用户名 - / soft / hard -nproc 1024

将它更改为更大的值到100k(需要sudo权限/ root),它应该适合你。

要详细了解安全政策,请参阅http://linux.die.net/man/5/limits.conf

答案 3 :(得分:3)

使用ulimit检查每个线程的堆栈大小,在我的例子中是Redhat Linux 2.6:

    ulimit -a
...
    stack size              (kbytes, -s) 10240

每个线程都会为它的堆栈分配这个内存量(10MB)。使用32位程序,最大地址空间为4GB,最大只有4096MB / 10MB = 409个线程!减去程序代码,减去堆空间可能会导致您观察到的最大值。 300个主题。

您应该能够通过编译64位应用程序或设置ulimit -s 8192甚至ulimit -s 4096来提高这一点。但如果这是可取的另一个讨论...

答案 4 :(得分:1)

除非你缩小默认的线程堆栈大小,否则你的内存也会耗尽。在我们的linux版本上它的10MB。

修改 错误代码12 =内存不足,所以我认为1mb堆栈对你来说仍然太大了。编译为32位,我可以得到一个100k堆栈给我30k线程。超过30k线程我得到错误代码11,这意味着不再允许线程。 1MB的堆栈在错误代码12之前给了我大约4k个线程.10MB给了我427个线程。 100MB给了我42个线程。 1 GB给了我4 ...我们有64位操作系统和64 GB RAM。你的OS是32位吗?当我编译64位时,我可以使用我想要的任何堆栈大小并获得线程限制。

另外我注意到如果我打开netbeans的分析内容(工具|分析)并从ide运行...我只能获得400个线程。奇怪的。如果你用尽所有线程,Netbeans也会死掉。

以下是您可以运行的测试应用:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>

// this prevents the compiler from reordering code over this COMPILER_BARRIER
// this doesnt do anything
#define COMPILER_BARRIER() __asm__ __volatile__ ("" ::: "memory")

sigset_t    _fSigSet;
volatile int    _cActive = 0;
pthread_t   thrd[1000000];

void * thread(void *i)
{
int nSig, cActive;

    cActive = __sync_fetch_and_add(&_cActive, 1);
    COMPILER_BARRIER();  // make sure the active count is incremented before sigwait

    // sigwait is a handy way to sleep a thread and wake it on command
    sigwait(&_fSigSet, &nSig); //make the thread still alive

    COMPILER_BARRIER();  // make sure the active count is decrimented after sigwait
    cActive = __sync_fetch_and_add(&_cActive, -1);
    //printf("%d(%d) ", i, cActive);
    return 0;
}

int main(int argc, char** argv)
{
pthread_attr_t attr;
int cThreadRequest, cThreads, i, err, cActive, cbStack;

    cbStack = (argc > 1) ? atoi(argv[1]) : 0x100000;
    cThreadRequest = (argc > 2) ? atoi(argv[2]) : 30000;

    sigemptyset(&_fSigSet);
    sigaddset(&_fSigSet, SIGUSR1);
    sigaddset(&_fSigSet, SIGSEGV);

    printf("Start\n");
    pthread_attr_init(&attr);
    if ((err = pthread_attr_setstacksize(&attr, cbStack)) != 0)
        printf("pthread_attr_setstacksize failed: err: %d %s\n", err, strerror(err));

    for (i = 0; i < cThreadRequest; i++)
    {
        if ((err = pthread_create(&thrd[i], &attr, thread, (void*)i)) != 0)
        {
            printf("pthread_create failed on thread %d, error code: %d %s\n", 
                     i, err, strerror(err));
            break;
        }
    }
    cThreads = i;

    printf("\n");

    // wait for threads to all be created, although we might not wait for 
    // all threads to make it through sigwait
    while (1)
    {
        cActive = _cActive;
        if (cActive == cThreads)
            break;
        printf("Waiting A %d/%d,", cActive, cThreads);
        sched_yield();
    }

    // wake em all up so they exit
    for (i = 0; i < cThreads; i++)
        pthread_kill(thrd[i], SIGUSR1);

    // wait for them all to exit, although we might be able to exit before 
    // the last thread returns
    while (1)
    {
        cActive = _cActive;
        if (!cActive)
            break;
        printf("Waiting B %d/%d,", cActive, cThreads);
        sched_yield();
    }

    printf("\nDone. Threads requested: %d.  Threads created: %d.  StackSize=%lfmb\n", 
     cThreadRequest, cThreads, (double)cbStack/0x100000);
    return 0;
}