多线程编程里开启和 CPU 核数相同的线程数真的有意义吗? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
kindjeff

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

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

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

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

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

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

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

    做的比较好的有 nginx, golang
    ldbC5uTBj11yaeh5
        9
    ldbC5uTBj11yaeh5  
       2016 年 11 月 5 日   1
    排队论的利特尔法则可以稍微解释了楼主的疑问,但是现实世界比排队论复杂很多。

    所以就各显神通了,目前 golang 是最棒哒。
    ldbC5uTBj11yaeh5
        10
    ldbC5uTBj11yaeh5  
       2016 年 11 月 5 日   1
    为什么说 golang 是最棒哒?

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

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

    如果你设置的线程数目大于核心数目,那么相当于在满载的时候,那么说明你目标程序肯定有至少两个线程在同一个 CPU 核心里面,而且是高负载状况。在这种情况下,操作系统就会频繁进行 CPU 调度,这是比较影响性能的一个地方,也就是所谓的平均周转时间变长
    kindjeff
        12
    kindjeff  
    OP
       2016 年 11 月 6 日 via iPhone
    @ovear 好的感谢回复,我理解这个意思了。那么是不是 cpu 密集型的 x 线程程序一定能充分利用 x 核 cpu 呢?不是的话同样会有多余调度。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2933 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 51ms UTC 00:19 PVG 08:19 LAX 17:19 JFK 20:19
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86