V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
git00ll
V2EX  ›  Java

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

  •  1
     
  •   git00ll · 2021-08-05 13:38:00 +08:00 · 5353 次点击
    这是一个创建于 1190 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    现象

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

    分析

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

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

    结论,尚未测试

    33 条回复    2021-08-06 18:16:42 +08:00
    jdjingdian
        1
    jdjingdian  
       2021-08-05 14:03:33 +08:00
    同问,因为经常看到开源项目编译命令推荐用“make -j $(($(nproc) + 1))”,不是很明白为什么要要比 CPU 线程数多 1
    wowo243
        2
    wowo243  
       2021-08-05 14:17:57 +08:00
    jdhao
        4
    jdhao  
       2021-08-05 14:34:40 +08:00 via Android
    CPU 密集型任务不是应该使用多进程? 你用多线程能使用多核的能力吗。一般多线程应该是用于网络 io 密集型场景。

    进程数太多不一定是好的,需要根据自己的任务做 benchmark
    lithiumii
        5
    lithiumii  
       2021-08-05 14:44:28 +08:00
    核心数呗,省下来的一点点利用率用于万一卡死了 ssh 还能连上去看看发生了什么(
    wanguorui123
        6
    wanguorui123  
       2021-08-05 14:49:56 +08:00
    多加几条没问题,比较关键的应用优先级调高点,防止分不到时间片卡死
    Geele
        7
    Geele  
       2021-08-05 14:53:42 +08:00
    @jdhao Java 多线程不能使用多核能力吗?
    Leviathann
        8
    Leviathann  
       2021-08-05 15:00:29 +08:00
    @jdhao CPU 密集必须多进程的不是 python 吗。。
    777777
        9
    777777  
       2021-08-05 15:07:16 +08:00
    用 go,不用管线程
    tabris17
        10
    tabris17  
       2021-08-05 15:12:17 +08:00
    经验?我看到还有说 CPU*2 的呢
    ikas
        11
    ikas  
       2021-08-05 15:35:41 +08:00
    ...这个肯定要看具体的用途..比如你的任务都是很快就执行完的..那线程就可以配置为 cpu 内核数量(左右),因为相当于每个线程一直在处理,不停顿..如果你的任务是有 io 相关,需要等待的..这时候你的线程数量限制主要是要考量你的内存能支持开多少个.
    cubecube
        12
    cubecube  
       2021-08-05 15:56:15 +08:00
    @tabris17 *2 肯定不是 cpu 密集型了。。
    其实有一个公式,就是算 io 和 cpu 的占比算的,我记得美团有个文章结过

    https://p0.meituan.net/travelcube/23a44974ff68a08261fb675242b83648181953.png
    Cloutain
        13
    Cloutain  
       2021-08-05 16:20:00 +08:00
    建议协程
    iceheart
        14
    iceheart  
       2021-08-05 16:31:09 +08:00 via Android   ❤️ 1
    还得看负载啊
    jdhao
        15
    jdhao  
       2021-08-05 16:32:05 +08:00 via Android
    @Geele Java 不太了解,Java 里面线程概念和其他似乎不一样
    dranfree
        16
    dranfree  
       2021-08-05 16:42:05 +08:00
    @jdhao 多线程就是为了充分利用 CPU 资源,怎么就不能使用多核能力了。。
    zavierx
        17
    zavierx  
       2021-08-05 16:45:09 +08:00
    @jdhao cpu 本来就是按线程调度的,为什么用不了多核?
    sununiq
        18
    sununiq  
       2021-08-05 17:07:06 +08:00
    ```java
    benchmark
    ```
    billlee
        19
    billlee  
       2021-08-05 17:19:28 +08:00
    @jdhao 这世上不是只有 cpython
    rayw0ng
        20
    rayw0ng  
       2021-08-05 18:06:40 +08:00
    kotlin coroutine 的 Dispatcher 默认线程数 = CPU 核心数,Dispatcher.IO 默认线程数 = 64,仅供参考。
    leeyom
        21
    leeyom  
       2021-08-05 18:32:10 +08:00
    io 密集型一般设置线程数 cpu 核心数*2
    cpu 密集型一般设置线程数 cpu 核心数+1 或者 -1 吧
    毕竟 cpu 密集型你线程数创建太多,上下文切换很浪费时间吧
    securityCoding
        22
    securityCoding  
       2021-08-05 18:35:50 +08:00
    @iceheart +1
    这个只是经验值而已,要得到准确的数值还得靠压测. 像很多 rpc 框架 io 线程数有的都给到 200 了
    jdhao
        23
    jdhao  
       2021-08-05 18:49:27 +08:00 via Android
    @billlee 好的,我孤陋寡闻了,对 Java 线程不了解
    chevalier
        24
    chevalier  
       2021-08-05 21:07:59 +08:00
    @jdhao 不要让语言限制了你的认知,大多数语言( C++,Java,Golang )多线程都可以吃多核的
    janus77
        25
    janus77  
       2021-08-05 22:01:19 +08:00
    理论要结合实践,如果你要做到完美那就是不同的项目应该使用不同的数量,就像楼上某一层回复说的,流量分布不平均都可能有不同的值,这意味着每一秒都可能有一个自己的最佳值,这种情况下你是无法做到完美的。所以只有两种方法
    第一是使用别人提供的建议值,不完美但是很接近完美
    第二是跑分,自己确定自己的项目应该使用的值。
    但是还是要记住 无论哪一个都做不到完美
    gBurnX
        26
    gBurnX  
       2021-08-06 00:48:35 +08:00
    1.计算机科学是一门工程学,而并非理论学科。所以,算法、各种分布式理论、人工智障等等,那些书本里的东西,也是工程经验的产物,你应付考试了解一下就行了,不要尽信。

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

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

    python ruby gil

    php 的多线程好像也有问题

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

    lua 好像也没有线程吧
    msg7086
        29
    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
        30
    leonme  
       2021-08-06 08:39:14 +08:00 via iPhone   ❤️ 3
    @Cloutain 都 cpu 密集型了,协程有啥用……
    Cloutain
        31
    Cloutain  
       2021-08-06 10:55:34 +08:00
    @leonme 尴尬了 不懂这一块
    Brentwans
        32
    Brentwans  
       2021-08-06 17:22:00 +08:00
    密集型的计算,核心数还是核心数+1 。偏向于+1,因为现实中 CPU 太快了,再密集的计算都难免有内存带来的延迟,增加一个来充分利用 CPU 。
    如果只是为了应用,得到合适的线程数,那实际情况远不是理论上一个公式那么简单,这个场景跑 benchmark 得出是最靠谱的。
    但是看了你这个问题描述,好像你或许不是需要多少个线程数,而是定位目前性能上不去的瓶颈是什么?还是先 profile 找到瓶颈点再去找解决方案吧
    goobai
        33
    goobai  
       2021-08-06 18:16:42 +08:00 via Android
    我咋觉得 cpu 密集型任务不应该超过核心数呢?是我太菜吗?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2365 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 16:10 · PVG 00:10 · LAX 08:10 · JFK 11:10
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.