максимальный поток на процесс в Linux - PullRequest
8 голосов
/ 12 апреля 2011

Я написал простую программу для расчета максимального количества потоков, которое может иметь процесс в 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 ]

17 голосов
/ 13 января 2012

Существует ограничение потока для linux , и его можно изменить во время выполнения, записав желаемое ограничение в /proc/sys/kernel/threads-max. Значение по умолчанию вычисляется из доступной системной памяти. В дополнение к этому пределу есть еще один предел: /proc/sys/vm/max_map_count, который ограничивает максимальное количество отображаемых сегментов, и по крайней мере последние ядра будут отображать память в каждом потоке. Если вы его достигнете, будет безопасно увеличить этот лимит.

Предел , который вы устанавливаете, - это недостаток виртуальной памяти в 32-битной операционной системе. Установите 64-битный Linux, если ваше оборудование поддерживает его, и все будет в порядке. Я могу легко запустить 30000 потоков с размером стека 8 МБ. Система имеет один Core 2 Duo + 8 ГБ системной памяти (в то же время я использую 5 ГБ для других задач) и работает под управлением 64-битной Ubuntu с ядром 2.6.32. Обратите внимание, что чрезмерное использование памяти (/ proc / sys / vm / overcommit_memory) должно быть разрешено, поскольку в противном случае системе потребуется как минимум 240 ГБ памяти для фиксации (сумма реальной памяти и пространства подкачки).

Если вам нужно много потоков и вы не можете использовать 64-битную систему, ваш единственный выбор - минимизировать использование памяти на поток для экономии виртуальной памяти. Начните с запроса как можно меньшего стека.

6 голосов
/ 12 апреля 2011

Возможно, системные ограничения не позволяют вам отображать стеки всех потоков, которые вам требуются. Посмотрите на /proc/sys/vm/max_map_count и увидите этот ответ . Я не уверен на 100%, что это ваша проблема, потому что большинство людей сталкиваются с проблемами при гораздо большем числе потоков .

4 голосов
/ 28 сентября 2013

Я также столкнулся с той же проблемой, когда мое количество потоков пересекает некоторый порог.Это было из-за ограничения уровня пользователя (количество процессов, которое пользователь может запустить за один раз), установленного на 1024 в /etc/security/limits.conf.

, поэтому проверьте ваш /etc/security/limits.confи найдите запись: -

имя пользователя - / soft / hard -nproc 1024

измените его на несколько больших значений на что-то 100k (требуются привилегии sudo / root), и это должно работать для вас.

Подробнее о политике безопасности см. http://linux.die.net/man/5/limits.conf.

3 голосов
/ 24 мая 2017

проверьте размер стека на поток с помощью ulimit, в моем случае Redhat Linux 2.6:

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

Каждый из ваших потоков получит этот объем памяти (10 МБ), выделенный для его стека. С 32-битной программой и максимальным адресным пространством 4 ГБ, это максимум только 4096 МБ / 10 МБ = 409 потоков !!! Минус программный код, минус куча пространства, вероятно, приведет к вашему наблюдаемому макс. из 300 нитей.

Вы можете поднять это, скомпилировав 64-битное приложение или установив ulimit -s 8192 или даже ulimit -s 4096. Но если это целесообразно, другое обсуждение ...

1 голос
/ 13 апреля 2011

Вам также не хватит памяти, если вы не уменьшите размер стека по умолчанию.Его 10 МБ в нашей версии Linux.

РЕДАКТИРОВАТЬ: Код ошибки 12 = недостаточно памяти, поэтому я думаю, что стек 1 МБ все еще слишком велик для вас.Скомпилированный для 32 бит, я могу получить стек 100 Кбайт, чтобы получить потоки 30 Кбайт.За 30k потоков я получаю код ошибки 11, что означает, что больше потоков не допускается.Стек 1 МБ дает мне около 4 тыс. Потоков до кода ошибки 12. 10 МБ дает мне 427 потоков.100 МБ дает мне 42 темы.1 ГБ дает мне 4 ... У нас 64-битная ОС с 64 ГБ оперативной памяти.Ваша ОС 32-битная?Когда я компилирую для 64-битной системы, я могу использовать любой размер стека, какой захочу, и получить предел потоков.

Также я заметил, что я включаю профилирование (Tools | Profiling) для netbeans и запускаю из ide...Я только могу получить 400 потоков.Weird.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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...