cpu 密集型任务,线程数应该等于核心数还是核心数+1

2021-08-05 13:38:00 +08:00
 git00ll

虽说是 cpu 密集型,但是也会有一些如打印日志这样的 io 操作,而且 logback 日志底层是堵塞的。 那么线程数应该等于核心数还是核心数+1 呢??

现象

执行 cpu 密集型操作,使用线程池数量等于 cpu 核心数,任务跑起来后,cpu 占用只能到 80%左右,无法充分利用。 猜测是因为任务中的日志部分涉及到资源堵塞和同步。

分析

增大一个线程数,好处是能利用其他线程输出日志堵塞时的 cpu 资源,缺点是增大了线程上下文切换消耗的资源。

当节省的资源 > 消耗的资源时,增大线程数是划算的,否则不划算。

结论,尚未测试

5370 次点击
所在节点    Java
33 条回复
leeyom
2021-08-05 18:32:10 +08:00
io 密集型一般设置线程数 cpu 核心数*2
cpu 密集型一般设置线程数 cpu 核心数+1 或者 -1 吧
毕竟 cpu 密集型你线程数创建太多,上下文切换很浪费时间吧
securityCoding
2021-08-05 18:35:50 +08:00
@iceheart +1
这个只是经验值而已,要得到准确的数值还得靠压测. 像很多 rpc 框架 io 线程数有的都给到 200 了
jdhao
2021-08-05 18:49:27 +08:00
@billlee 好的,我孤陋寡闻了,对 Java 线程不了解
chevalier
2021-08-05 21:07:59 +08:00
@jdhao 不要让语言限制了你的认知,大多数语言( C++,Java,Golang )多线程都可以吃多核的
janus77
2021-08-05 22:01:19 +08:00
理论要结合实践,如果你要做到完美那就是不同的项目应该使用不同的数量,就像楼上某一层回复说的,流量分布不平均都可能有不同的值,这意味着每一秒都可能有一个自己的最佳值,这种情况下你是无法做到完美的。所以只有两种方法
第一是使用别人提供的建议值,不完美但是很接近完美
第二是跑分,自己确定自己的项目应该使用的值。
但是还是要记住 无论哪一个都做不到完美
gBurnX
2021-08-06 00:48:35 +08:00
1.计算机科学是一门工程学,而并非理论学科。所以,算法、各种分布式理论、人工智障等等,那些书本里的东西,也是工程经验的产物,你应付考试了解一下就行了,不要尽信。

2.实际工程,并不是非黑即白,比如全是 CPU 密集型,或者全是日志打印这种非 CPU 密集型。你要根据项目实际的情况,去收集具体任务执行情况,分析两种具体任务的百分比、执行顺序等等多种因素。

3.判断一项原理的优缺点,也要看大局。比如很多人觉得 Python 性能差,但很多应用 Python 的地方,并不差钱,他们追求的是最高的开发效率,以及尽量集中注意力到业务上而非各种细节优化上。
msg7086
2021-08-06 00:54:05 +08:00
@jdhao 只有有全局线程锁 GIL 的语言才会被线程束缚。
Python 和 Ruby 这类语言(的官方实现)才是特例。大部分语言实现都是没有这种强制线程锁的,多线程设计出来本来就是用来占满 CPU 资源的。
chenqh
2021-08-06 01:36:12 +08:00
@msg7086 不是大部分脚本语言多线程实现都有问题吗?

python ruby gil

php 的多线程好像也有问题

nodejs 一开始根本就不支持线程

lua 好像也没有线程吧
msg7086
2021-08-06 02:36:08 +08:00
@chenqh Python 和 Ruby 也是“官方实现”才用到了 GIL 。
换句话说只有 CPython 和 Ruby MRI 才有 GIL 的概念。
Jython 和 JRuby 都是没有 GIL 的。Rubinius 也很早就移除了 GIL 。
GIL 主要是省心,不用折腾 C 库的线程安全,解释器实现起来也方便。

脚本语言原本也算是一种特例了。C/C++/Java/C#这些常用语言的实现都是没有 GIL 的。

至于 PHP 和 JS 说起来就比较复杂了。PHP 本身是支持多线程的,但是语言实现内部没有做多线程,因为 PHP 原本就不是用来做 CPU 密集型任务的。PHP 的多线程是体现在调用端的,可以起一大堆单线程运行的 PHP 线程。JS 也是设计之初就没有考虑多线程。他们都是有特殊的应用场景的。
leonme
2021-08-06 08:39:14 +08:00
@Cloutain 都 cpu 密集型了,协程有啥用……
Cloutain
2021-08-06 10:55:34 +08:00
@leonme 尴尬了 不懂这一块
Brentwans
2021-08-06 17:22:00 +08:00
密集型的计算,核心数还是核心数+1 。偏向于+1,因为现实中 CPU 太快了,再密集的计算都难免有内存带来的延迟,增加一个来充分利用 CPU 。
如果只是为了应用,得到合适的线程数,那实际情况远不是理论上一个公式那么简单,这个场景跑 benchmark 得出是最靠谱的。
但是看了你这个问题描述,好像你或许不是需要多少个线程数,而是定位目前性能上不去的瓶颈是什么?还是先 profile 找到瓶颈点再去找解决方案吧
goobai
2021-08-06 18:16:42 +08:00
我咋觉得 cpu 密集型任务不应该超过核心数呢?是我太菜吗?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/793833

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX