Максимальное количество потоков на процесс в Linux?


245

Какое максимальное количество потоков может быть создано процессом в Linux?

Как (если возможно) это значение может быть изменено?

Ответы:


247

В Linux нет отдельных потоков на лимит процессов, только ограничение на общее количество процессов в системе (потоки - это, по сути, просто процессы с общим адресным пространством в Linux), которое вы можете посмотреть так:

cat /proc/sys/kernel/threads-max

По умолчанию используется количество страниц памяти / 4. Вы можете увеличить это как:

echo 100000 > /proc/sys/kernel/threads-max

Существует также ограничение на количество процессов (и, следовательно, потоков), которые может создать один пользователь, см. ulimit/getrlimitПодробности относительно этих ограничений.


3
Ограничение в / proc / sys / vm / max_map_count также может ограничивать количество потоков. Должно быть безопасно увеличить этот лимит, если вы его достигнете.
Микко Ранталайнен

1
Роберт: Linux реализует ограничение на процесс косвенно. Проверьте мой ответ для деталей;)
codersofthedark

Я пытаюсь изменить это на моем Ubuntu 12.04, и это не меняется с вашей командой. Я также попробовал vi, чтобы изменить его, но получаю, E667: Fsync failedкогда пытаюсь сэкономить на vi.
Сиддхарт

4
@dragosrsupercool Максимальный поток рассчитывается с использованием общего оперативной памяти, без виртуальной памяти
c4f4t0r

1
Размер стека на поток (по умолчанию в вашей системе), скорее всего, будет пределом, чем что-либо еще. Уменьшение размера стека для каждого потока - это способ увеличить общее количество потоков (хотя это редко хорошая идея).
Рэнди Ховард

67

Неверно говорить, что в LINUX нет отдельных потоков на ограничение процесса.

Linux реализует максимальное количество потоков на процесс косвенно !!

number of threads = total virtual memory / (stack size*1024*1024)

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

Проверьте свою машину:

Всего виртуальной памяти: ulimit -v(по умолчанию не ограничено, поэтому вам нужно увеличить объем подкачки, чтобы увеличить это)

Общий размер стека: ulimit -s(по умолчанию 8Mb)

Команда для увеличения этих значений:

ulimit -s newvalue

ulimit -v newvalue

* Замените новое значение значением, которое вы хотите установить в качестве предела.

Ссылки:

http://dustycodes.wordpress.com/2012/02/09/increasing-number-of-threads-per-process/


11
За исключением 3 маленьких деталей: 1. Linux не делает этого, наличие стеков и тот факт, что память и адресное пространство имеют конечный размер, не имеют к этому никакого отношения. 2. Вы должны указать стек потока при его создании, это не зависит от ulimit -s. Вполне возможно (не разумно, но возможно) создать столько потоков, сколько существует возможных идентификаторов потоков. В 64-битном Linux даже легко «возможно» создать больше потоков, чем их идентификаторов (конечно, это невозможно, но в отношении стека это так). 3. Резерв стека, коммит и виртуальная машина - это разные вещи, особенно с OC.
Деймон

Да, чтобы увеличить количество потоков, вам нужно увеличить виртуальную память или уменьшить размер стека. В Raspberry Pi я не нашел способа увеличить виртуальную память, если уменьшить размер стека с 8 МБ до 1 МБ. Возможно, получится более 1000 потоков на процесс, но уменьшить размер стека с помощью команды «ulimit -s» сделать это для всех потоков. Итак, мое решение было использовать экземпляр «pthread_t» «класс потока», потому что pthread_t позволяет мне устанавливать размер стека для каждого потока. Наконец, я могу архивировать более 1000 потоков на процесс в Raspberry Pi каждый с 1
МБ

43

С практической точки зрения предел обычно определяется пространством стека. Если каждый поток получает 1 МБ стека (я не помню, если это по умолчанию в Linux), то у вас 32-разрядная система исчерпает адресное пространство после 3000 потоков (при условии, что последний ГБ зарезервирован для ядра) ,

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

Что вы делаете, когда этот предел даже актуален?


3
1 МБ на поток для стека довольно велик, многим программам не нужно нигде рядом с таким большим пространством стека. Производительность будет зависеть от количества запущенных процессов, а не от числа существующих потоков. У меня сейчас работает машина с 1200+ потоков с нагрузкой 0,40.
Роберт Гэмбл

13
производительность зависит от того, что делают потоки. Вы можете пойти намного выше, чем на несколько десятков, если они мало что делают и, следовательно, меньше переключают контекст.
Кори Голдберг

стек динамически растет, только начальная страница выделяется вне очереди
Михаил Панков

28

правильные темы 100k на Linux:

ulimit -s  256
ulimit -i  120000
echo 120000 > /proc/sys/kernel/threads-max
echo 600000 > /proc/sys/vm/max_map_count
echo 200000 > /proc/sys/kernel/pid_max 

 ./100k-pthread-create-app

Обновление 2018 от @Thomas для систем systemd:

/etc/systemd/logind.conf: UserTasksMax=100000

4
Спасибо, это наконец-то позволило мне пробиться через 32-килобайтный поток Java.
Березовский

1
У меня не работает: $ ulimit -s 100000 $ ulimit -i 63645 $ cat / proc / sys / kernel / threads-max 127626 $ cat / proc / sys / vm / max_map_count 600000 $ cat / proc / sys / kernel / pid_max 200000 $ java -Xmx4G -Xss256k -cp. ThreadCreation ... 11542 11543 java.lang.OutOfMemoryError: невозможно создать новый собственный поток в java.lang.Thread.start0 (собственный метод) в java.lang.Thread.start (Thread.java:717) в ThreadCreation.main ( ThreadCreation.java:15)
Martin Vysny

@MartinVysny ulimit -s = размер резьбы в кб. поэтому вы пытаетесь создать потоки с размером стека 100 МБ.
Владимир Кунщиков

добавил ваше предложение без проверки, @Thomas, спасибо за отзыв в любом случае.
Владимир Кунщиков

2
@VladimirKunschikov Спасибо, приятель, твое решение действительно сработало, и спасибо Томасу за добавление этой дополнительной строки, я могу подтвердить, что она не сработает без этой строки.
BillHoo

14

@dragosrsupercool

Linux не использует виртуальную память для вычисления максимального потока, но физический ОЗУ установлен в системе

 max_threads = totalram_pages / (8 * 8192 / 4096);

http://kavassalis.com/2011/03/linux-and-the-maximum-number-of-processes-threads/

ядро / fork.c

/* The default maximum number of threads is set to a safe
 * value: the thread structures can take up at most half
 * of memory.
 */
max_threads = mempages / (8 * THREAD_SIZE / PAGE_SIZE);

Таким образом, максимальный поток в каждой системе различен, потому что установленный ram может быть разных размеров, я знаю, что Linux не нужно увеличивать виртуальную память, потому что на 32-разрядной системе мы получили 3 ГБ для пользовательского пространства и 1 ГБ для ядра, в 64-битной системе мы получили 128 ТБ виртуальной памяти, что происходит в Solaris, если вы хотите увеличить виртуальную память, вам нужно добавить пространство подкачки.


11

Чтобы получить его:

cat /proc/sys/kernel/threads-max

Чтобы установить это:

echo 123456789 > /proc/sys/kernel/threads-max

123456789 = количество потоков


При попытке записи мне отказывают в разрешении, даже с правами root.
Ким

Ну, прошло уже почти десять лет с тех пор, как это было опубликовано. Я не в курсе текущего положения вещей, но многое могло измениться (и, вероятно, изменилось) ...
Винсент Ван Ден Берге

проблема с perm-deny может быть append ( >) часть теряет sudo: tryecho 12345678 | sudo tee -a /proc/sys/kernel/threads-max
dwanderson

10

Предел количества потоков:

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

Как рассчитывается:

max_threads = mempages / (8 * THREAD_SIZE / PAGE_SIZE);

и: размер страницы x86_64 (PAGE_SIZE) составляет 4 КБ; Как и во всех других архитектурах, x86_64 имеет стек ядра для каждого активного потока. Эти стеки потоков имеют размер THREAD_SIZE (2 * PAGE_SIZE);

для бугорков:

cat /proc/zoneinfo | grep spanned | awk '{totalpages=totalpages+$2} END {print totalpages}';

так что на самом деле это число не связано с ограничением размера стека памяти потока (ulimit -s ).

PS: ограничение стека памяти в моей виртуальной виртуальной машине составляет 10 МБ, а для 1,5 ГБ памяти эта виртуальная машина может позволить себе только 150 потоков?


5

Для тех, кто смотрит на это сейчас, в системах systemd (в моем случае, в частности, в Ubuntu 16.04) есть еще одно ограничение, устанавливаемое параметром cgroup pids.max.

По умолчанию это значение равно 12 288, и его можно переопределить в /etc/systemd/logind.conf.

Другие рекомендации по-прежнему применимы, включая pids_max, threads-max, max_maps_count, ulimits и т. Д.


5

проверьте размер стека на поток с помощью 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. Но если это целесообразно, другое обсуждение ...


4

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


3
Целью многопоточности является не только производительность. Например, вы слушаете 10 портов с системой блокировки на 4-х ядерном процессоре. В этом примере нет значения 4.
obayhan

3

Используйте nbio неблокирующую библиотеку ввода-вывода или что-то еще, если вам нужно больше потоков для выполнения вызовов ввода-вывода, которые блокируют


2

Зависит от вашей системы, просто напишите пример программы [путем создания процессов в цикле] и проверьте, используя ps axo pid, ppid, rss, vsz, nlwp, cmd. Когда он больше не может создавать потоки, проверьте количество nlwp [nlwp - количество потоков] вуаля, вы получили свой надежный ответ вместо того, чтобы идти по книгам



0

Мы можем увидеть максимальное количество потоков, определенных в следующем файле в Linux

cat / proc / sys / kernel / threads-max

(ИЛИ)

sysctl -a | grep threads-max


0

Вы можете увидеть текущее значение с помощью следующей команды: cat / proc / sys / kernel / threads-max

Вы также можете установить значение как

echo 100500> / proc / sys / kernel / threads-max

Установленное вами значение будет проверено по доступным страницам ОЗУ. Если структуры потоков занимают более 1/8 всех доступных страниц ОЗУ, то максимальный поток будет соответственно уменьшен.


0

Да, чтобы увеличить количество потоков, вам нужно увеличить виртуальную память или уменьшить размер стека. В Raspberry Pi я не нашел способа увеличить виртуальную память, если уменьшить размер стека с 8 МБ до 1 МБ. Возможно, получится более 1000 потоков на процесс, но уменьшить размер стека с помощью команды «ulimit -s» сделать это для всех потоков. Итак, мое решение было использовать экземпляр «pthread_t» «класс потока», потому что pthread_t позволяет мне устанавливать размер стека для каждого потока. Наконец, я могу архивировать более 1000 потоков на процесс в Raspberry Pi, каждый из которых имеет 1 МБ стека.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.