Каково максимальное количество потоков, которые может создать pthread? [дубликат]

Возможные Дубликаты:
поток, созданный pthread_create то же самое с потоком ядра?

я использую приведенный ниже код для проверки максимального количества потоков, которые может создать функция pthread_create.

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

static unsigned long long thread_nr = 0;

pthread_mutex_t mutex_;

void* inc_thread_nr(void* arg) {
    (void*)arg;
    pthread_mutex_lock(&mutex_);
    thread_nr ++;
    pthread_mutex_unlock(&mutex_);

    /* printf("thread_nr = %dn", thread_nr); */

    sleep(300000);
}

int main(int argc, char *argv[])
{
    int err;
    int cnt = 0;

    pthread_t pid[1000000];

    pthread_mutex_init(&mutex_, NULL);

    while (cnt < 1000000) {

        err = pthread_create(&pid[cnt], NULL, (void*)inc_thread_nr, NULL);
        if (err != 0) {
            break;
        }
        cnt++;
    }

    pthread_join(pid[cnt], NULL);

    pthread_mutex_destroy(&mutex_);
    printf("Maximum number of threads per process is = %dn", thread_nr);
}

и выход:

Maximum number of threads per process is = 825

это максимальное количество потоков, которое может создать функция pthread_create?

кроме того, я использую команду ниже для просмотра максимального количества потоков моя система позволяет:

# cat /proc/sys/kernel/threads-max

и номер 772432.

почему выход моей программы не равно значению threads-max ?

моя ОС-Fodaro 16, С 12 ядрами, 48G ОЗУ.

3 ответов


размер по умолчанию для стека на поток искусственно накладывает ограничение в вашем тесте. В то время как стек по умолчанию для процесса (исходный поток) растет динамически, по мере необходимости, стеки для других потоков фиксированного размера. Размер по умолчанию обычно очень большой, что-то вроде двух мегабайт, чтобы убедиться, что стек на поток достаточно велик даже для патологических случаев (глубокая рекурсия и так далее).

в большинстве случаев, работникам потока нужно очень маленький стек. Я обнаружил, что на всех архитектурах, которые я использовал, достаточно 64K (65536 байт) на стек потока, если я не использую глубоко рекурсивные алгоритмы или большие локальные переменные (структуры или массивы).

чтобы явно указать размер стека для каждого потока, измените свой main() Для что-то вроде следующего:

#define MAXTHREADS 1000000
#define THREADSTACK  65536

int main(int argc, char *argv[])
{
    pthread_t       pid[MAXTHREADS];
    pthread_attr_t  attrs;
    int  err, i;
    int  cnt = 0;

    pthread_attr_init(&attrs);
    pthread_attr_setstacksize(&attrs, THREADSTACK);

    pthread_mutex_init(&mutex_, NULL);

    for (cnt = 0; cnt < MAXTHREADS; cnt++) {

        err = pthread_create(&pid[cnt], &attrs, (void*)inc_thread_nr, NULL);
        if (err != 0)
            break;
    }

    pthread_attr_destroy(&attrs);

    for (i = 0; i < cnt; i++)
        pthread_join(pid[i], NULL);

    pthread_mutex_destroy(&mutex_);

    printf("Maximum number of threads per process is %d (%d)\n", cnt, thread_nr);
}

отметим, что attrs не потребляется pthread_create() звонок. Подумайте о атрибутах потока больше как о шаблоне how pthread_create() создать нити; они не являются атрибутами данного потока. Это срабатывает много начинающих программистов pthreads, так что это одна из тех вещей, которые вам лучше получить прямо с самого начала.

Что касается самого размера стека, он должен быть по крайней мере PTHREAD_STACK_MIN (16384 в Linux, я считаю) и делится на sysconf(_SC_PAGESIZE). Поскольку размер страницы-это сила двух на всех архитектурах, использование достаточно большой силы двух всегда должно работать.

кроме того, я добавил исправление в ней есть. Вы только попробуйте присоединиться к несуществующему потоку (тот, который цикл пытался создать, но не удалось), но вам нужно присоединиться ко всем из них (чтобы убедиться, что они все сделали свою работу).

дополнительные рекомендуемые исправления:

вместо использования сна используйте переменную условия. Пусть каждый поток ждет (pthread_cond_wait()) в переменной условия (удерживая мьютекс), затем отпустите мьютекс и выйдите. Таким образом, ваша основная функция должна только транслировать (pthread_cond_broadcast()) на переменной условия, чтобы сказать все потоки теперь они могут выйти, затем он может присоединиться к каждому из них, и вы можете быть уверены, что это количество потоков действительно работает одновременно. Поскольку ваш код стоит сейчас, у некоторых потоков может быть достаточно времени, чтобы проснуться от сна и выйти.


теоретически, нет ограничений на количество потоков, которые может иметь процесс. Но практическое ограничение может исходить из того, что все потоки разделяют ресурсы.

Это означает, что в какой-то момент процесс не может создать больше определенного количества процессов из-за отсутствия ресурсов для совместного использования с таким пространством стека, например.


по данным pthread_create(3) man page, есть еще один предел:

RLIMIT_NPROC soft resource limit (set via setrlimit(2)), which limits the number 
of process  for  a real user ID.

попробуйте найти значение этого предела с помощью getrlimit(2). Если значение по-прежнему не соответствует измеренному вами числу (825), попробуйте изменить это ограничение на setrlimit(2) чтобы проверить, влияет ли это на ваши измерения.

EDIT: на самом деле предельное значение RLIMIT_NPROC такое же, как и полученное с помощью команды оболочки ulimit -u (который печатает / устанавливает максимальные пользовательские процессы).