Linux中每个进程的最大线程数?


245

Linux下一个进程可以创建的最大线程数是多少?

如何(如果可能)修改此值?

Answers:


246

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中的限制也可能会限制线程数。如果您将其提高很多,应该是安全的。
Mikko Rantalainen 2012年

1
Robert:Linux确实间接实现了每个进程的限制。检查我的答案以获取详细信息;)
codersofthedark 2012年

我试图在我的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。很可能(不明智,但是可能)创建尽可能多的线程ID。在64位Linux下,创建超过线程ID的线程甚至很容易(可能)(当然不可能,但是就堆栈而言)。3.堆栈保留,提交和VM是不同的,尤其是在OC中。
达蒙

是的,要增加线程数,您需要增加虚拟内存或减小堆栈大小。在Raspberry Pi中,我没有找到增加虚拟内存的方法,如果将堆栈大小从默认的8MB减小到1MB,则可能每个进程获得1000个以上的线程,但是使用“ ulimit -s”命令减小了堆栈大小。使这适用于所有线程。因此,我的解决方案是使用“ pthread_t”实例“线程类”,因为pthread_t允许我设置每个线程的堆栈大小。最后,我可以在Raspberry Pi中为每个进程存档1000多个线程,每个线程具有1MB的堆栈
Deulis

43

实际上,限制通常由堆栈空间确定。如果每个线程获得一个1MB的堆栈(我不记得这是Linux上的默认值),那么一个32位系统将在3000个线程之后用完地址空间(假设最后一个gb保留给内核) 。

但是,如果使用多个线程,您很可能会遇到糟糕的性能。迟早,您将获得太多的上下文切换开销,调度程序中的太多开销,等等。(创建大量线程并不会消耗大量内存。但是,许多需要实际工作的线程会减慢您的速度,因为它们正在争取可用的CPU时间)

在这个限制还很重要的地方,您正在做什么?


3
每个线程1 MB的堆栈空间非常大,许多程序不需要那么多堆栈空间。性能将基于可运行进程的数量,而不是基于存在的线程的数量。我有一台正在运行的计算机,其中有1200多个线程,负载为0.40。
罗伯特·格兰伯

13
性能取决于线程在做什么。如果他们不做很多事情,那么上下文切换就可以比几十个要高得多。
科里·戈德堡

堆栈动态增长,只有初始页面被
即时

28

在Linux上正确的100k线程:

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

@Thomas在系统系统上的2018年更新:

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

4
谢谢,它终于使我突破了32k Java线程计数。
berezovskyi

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:无法在ThreadCreation.main(的java.lang.Thread.start(Thread.java:717)的java.lang.Thread.start0(本机方法)处创建新的本机线程ThreadCreation.java:15)
马丁Vysny

@MartinVysny ulimit -s =线程大小(以kb为单位)。因此,您尝试创建线程堆栈大小为100MB的线程。
弗拉基米尔·昆斯基科夫(Fladimir Kunschikov)'11

在未检查的情况下添加了您的建议,@ Thomas,仍然感谢您的反馈。
弗拉基米尔·昆斯基科夫(Fladimir Kunschikov)

2
@VladimirKunschikov感谢朋友,您的解决方案确实有效,并且感谢Thomas添加了该额外的行,我可以确定它超出该行将无法使用。
BillHoo '18年

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 GB的用户空间和1 GB的内核,在64位系统上,我们获得了128 TB的虚拟内存,这是在Solaris上发生的,如果要增加虚拟内存,则需要添加交换空间。


11

要检索它:

cat /proc/sys/kernel/threads-max

要设置它:

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

123456789 =线程数


尝试写入时,即使使用root,我也被拒绝权限。
金(Kim)

好吧,自发布以来已有近十年了。我还没有掌握最新的情况,但是可能已经发生了很多变化(可能已经发生了变化)……
Vincent Van Den Berghe

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)为4K;与所有其他体系结构一样,x86_64对于每个活动线程都有一个内核堆栈。这些线程栈大THREAD_SIZE(2 * PAGE_SIZE);

用于提示:

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

因此实际上,该数字与线程存储器堆栈大小(ulimit -s)的限制无关。

PS:在我的rhel VM中,线程内存堆栈限制为10M,而对于1.5G内存,此VM只能提供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

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

您应该能够通过在64位上编译和运行或设置ulimit -s 8192甚至ulimit -s 4096来提出这一问题。但是,如果这是可取的,那就再讨论一次...


4

可能没关系。将算法设计为使用固定数量的线程(例如,如果具有4或8个处理器,则为4或8)将获得更好的性能。您可以使用工作队列,异步IO或类似libevent的方法来执行此操作。


3
多线程的目的不仅在于性能。例如,您正在使用4核处理器上的阻塞系统监听10个端口。在此示例中没有意义
4。– obayhan

3

nbio 如果您需要更多线程来执行阻塞的I / O调用,请使用非阻塞I / O库或其他方法


2

取决于您的系统,只需编写示例程序[通过在循环中创建进程]并使用ps axo pid,ppid,rss,vsz,nlwp,cmd进行检查。当它无法再创建线程时,请检查nlwp的计数[nlwp是线程数]瞧,您会得到万无一失的答案,而不必翻阅书本




0

您可以通过以下命令查看当前值-cat / proc / sys / kernel / threads-max

您还可以将值设置为

回声100500> / proc / sys / kernel / threads-max

将根据可用的RAM页面检查您设置的值。如果线程结构占用了可用RAM页的1/8以上,则线程最大数将相应减少。


0

是的,要增加线程数,您需要增加虚拟内存或减小堆栈大小。在Raspberry Pi中,我没有找到增加虚拟内存的方法,如果将堆栈大小从默认的8MB减小到1MB,则可能每个进程获得1000个以上的线程,但是使用“ ulimit -s”命令减小了堆栈大小。使这适用于所有线程。因此,我的解决方案是使用“ pthread_t”实例“线程类”,因为pthread_t允许我设置每个线程的堆栈大小。最后,我可以在Raspberry Pi中为每个进程归档1000多个线程,每个线程具有1MB的堆栈。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.