多线程编程里开启和 CPU 核数相同的线程数真的有意义吗?

2016-11-05 10:36:08 +08:00
 kindjeff
一些多线程编程的资料建议开启和 CPU 核数相同的线程数,说是有利于多核并行执行。
操作系统管理的进程和线程很多,有没有可能长期处于这样一种情况:双核 CPU ,一个程序开启了两个线程。但是有一个核长期在处理其他进程,所以只有一个核在处理这个程序的两个线程(以及其他进程)。
这种情况下开启两条线程不会比开启更多线程要好。
4846 次点击
所在节点    问与答
12 条回复
ovear
2016-11-05 11:33:22 +08:00
LZ 的操作系统没学好啊。。
这是操作系统调度的事情,现在的操作系统不可能就你的两个线程的,所以上述事情有可能发生。
虽然操作系统会进行调度,但是也会产生切换的额外开销的(周转时间)
建议去看 http://baike.baidu.com/view/399160.htm

至于具体的 CPU 占用,可以去看 Windows 的资源监视器,或者 Linux 的 top 中 cpu 那行, sirq 那个数值就是调度所产生的周转时间

https://moetu.org/images/2016/11/05/2016-11-051132425a463.png

UNDERSTANDING LINUX CPU STATS
http://blog.scoutapp.com/articles/2015/02/24/understanding-linuxs-cpu-stats
ovear
2016-11-05 11:38:09 +08:00
噢补充一句,的确有 CPU BOUND THREAD 的,但是除非你手动制定,不然都是由操作系统进行调度的。(当然就算你程序使用 100%的 CPU ,操作系统也不会把所有 CPU 调度给你的,不然其他进程就没有资源了)
多线程的意义在于,能同时使用多个核心的 CPU 。在高负载情况下,可以跑满线程个数的 CPU 。单线程就只能跑满一个核心,对于服务器来说,同时面向多个独立的用户,相互没有关联,开线程再合适不过了
caixiexin
2016-11-05 11:54:41 +08:00
看是计算密集型还是 io 密集型,前者开一和核心数一样的线程数才有效果。还有就是编程语言, Python2.x 用这种方式也不能最大利用 CPU 。
kindjeff
2016-11-05 12:24:50 +08:00
@ovear 你说的貌似和我问的没什么关系吧。我的意思是一些资料里推荐的开启和 CPU 核数相同的线程数是有意义的吗。

@caixiexin 即使是计算密集型,在我举例的情况下,双线程也不会比更多线程好啊;因为 Python 的多线程确实是不能多核并行的,本身开启和 CPU 核数相同的线程数就没有什么意义。
ldbC5uTBj11yaeh5
2016-11-05 12:25:43 +08:00
来来来,安利一下, go 语言大法好。
honeycomb
2016-11-05 12:48:21 +08:00
@kindjeff
线程的上下文切换有开销,但多数时候比不过尽量占用所有核心带来的好处。

Python 有 Python 的事情
可是你问的明明是类似这样的:

make -j K , K 的建议值是系统可使用的逻辑内核数量

至于“有一个核在长期处理其它情况”,不意味着系统不会把其它情况的资源让出来。
kindjeff
2016-11-05 12:59:41 +08:00
@honeycomb 我的疑问大概等价于:双线程的程序的两个线程,能确保用到两个核心吗?如果很多情况下不能的话,用双线程并不一定就比三线程好。
ldbC5uTBj11yaeh5
2016-11-05 13:13:01 +08:00
@kindjeff 不考虑到 IO 等待,的确是线程(进程)数 = CPU 核数最好。

加入 IO 等待因数就非常复杂,实践的做法是
1. 把 network io 都异步(非阻塞)化。
2. 把 file io 搞成伪异步话(底层一般还是一个透明不可见的独立线程池)

做的比较好的有 nginx, golang
ldbC5uTBj11yaeh5
2016-11-05 13:14:53 +08:00
排队论的利特尔法则可以稍微解释了楼主的疑问,但是现实世界比排队论复杂很多。

所以就各显神通了,目前 golang 是最棒哒。
ldbC5uTBj11yaeh5
2016-11-05 13:24:33 +08:00
为什么说 golang 是最棒哒?

解决现实问题的模型大约有下面三种
1. nginx 是多进程+状态机,门槛太高。(当然 ngx_lua/openrestry 降低这个门槛)
2. golang 是多核协程,无脑傻瓜。(小学生都会写并发 /并行程序了)
3. mac 的 gcd, intel 的 tbb , 大多用来处理特定的领域问题,学习成本也不友好。

至于带 GIL 脚本语言加多进程,呵呵,那能叫高并发程序么?
ovear
2016-11-06 00:49:56 +08:00
@kindjeff 当然有关系,系统里面存在的线程不可能只有你程序的那几个。你打开任务管理器-线程看看就知道了。
既然这样,如果你目标程序,线程数目<核心数目,那样在满载的时候,是无法跑满所有核心的。

如果你设置的线程数目大于核心数目,那么相当于在满载的时候,那么说明你目标程序肯定有至少两个线程在同一个 CPU 核心里面,而且是高负载状况。在这种情况下,操作系统就会频繁进行 CPU 调度,这是比较影响性能的一个地方,也就是所谓的平均周转时间变长
kindjeff
2016-11-06 08:24:55 +08:00
@ovear 好的感谢回复,我理解这个意思了。那么是不是 cpu 密集型的 x 线程程序一定能充分利用 x 核 cpu 呢?不是的话同样会有多余调度。

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

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

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

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

© 2021 V2EX