V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
kindjeff
V2EX  ›  问与答

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

  •  1
     
  •   kindjeff · 2016-11-05 10:36:08 +08:00 via iPhone · 4847 次点击
    这是一个创建于 2932 天前的主题,其中的信息可能已经有所发展或是发生改变。
    一些多线程编程的资料建议开启和 CPU 核数相同的线程数,说是有利于多核并行执行。
    操作系统管理的进程和线程很多,有没有可能长期处于这样一种情况:双核 CPU ,一个程序开启了两个线程。但是有一个核长期在处理其他进程,所以只有一个核在处理这个程序的两个线程(以及其他进程)。
    这种情况下开启两条线程不会比开启更多线程要好。
    12 条回复    2016-11-06 08:24:55 +08:00
    ovear
        1
    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
        2
    ovear  
       2016-11-05 11:38:09 +08:00
    噢补充一句,的确有 CPU BOUND THREAD 的,但是除非你手动制定,不然都是由操作系统进行调度的。(当然就算你程序使用 100%的 CPU ,操作系统也不会把所有 CPU 调度给你的,不然其他进程就没有资源了)
    多线程的意义在于,能同时使用多个核心的 CPU 。在高负载情况下,可以跑满线程个数的 CPU 。单线程就只能跑满一个核心,对于服务器来说,同时面向多个独立的用户,相互没有关联,开线程再合适不过了
    caixiexin
        3
    caixiexin  
       2016-11-05 11:54:41 +08:00 via Android
    看是计算密集型还是 io 密集型,前者开一和核心数一样的线程数才有效果。还有就是编程语言, Python2.x 用这种方式也不能最大利用 CPU 。
    kindjeff
        4
    kindjeff  
    OP
       2016-11-05 12:24:50 +08:00
    @ovear 你说的貌似和我问的没什么关系吧。我的意思是一些资料里推荐的开启和 CPU 核数相同的线程数是有意义的吗。

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

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

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

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

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

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

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

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

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

    如果你设置的线程数目大于核心数目,那么相当于在满载的时候,那么说明你目标程序肯定有至少两个线程在同一个 CPU 核心里面,而且是高负载状况。在这种情况下,操作系统就会频繁进行 CPU 调度,这是比较影响性能的一个地方,也就是所谓的平均周转时间变长
    kindjeff
        12
    kindjeff  
    OP
       2016-11-06 08:24:55 +08:00 via iPhone
    @ovear 好的感谢回复,我理解这个意思了。那么是不是 cpu 密集型的 x 线程程序一定能充分利用 x 核 cpu 呢?不是的话同样会有多余调度。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2867 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 02:34 · PVG 10:34 · LAX 18:34 · JFK 21:34
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.