听说 Python 的多线程是假的,无法利用多核心? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
James369
V2EX    Python

听说 Python 的多线程是假的,无法利用多核心?

  •  1
     
  •   James369 2020-10-27 15:03:43 +08:00 6173 次点击
    这是一个创建于 1859 天前的主题,其中的信息可能已经有所发展或是发生改变。
    貌似 js 也是单线程,唉,脚本语言。。

    查了一下 python 有一个叫 GIL 的全局锁,本质上无法做到多 CPU 核心的同时利用了?

    那我现在有几个重 CPU 的任务,只能用多进程来实现了?还得搞多进程通信。。
    第 1 条附言    2020-10-27 17:20:32 +08:00
    不好意思,在我的思维里面,多线程=并发执行。今天学到了不少 python 编程知识,谢谢。
    31 条回复    2020-11-02 01:39:24 +08:00
    coderluan
        1
    coderluan  
       2020-10-27 15:15:19 +08:00
    调 C 的多线程就行, 不要用多进程
    coderxy
        2
    coderxy  
       2020-10-27 16:03:28 +08:00
    nodejs 就是无法利用多核心,所以会起多个进程。 不过现在很多都是 k8s 环境下,单个 pod 只利用单核心也没毛病。
    James369
        3
    James369  
    OP
       2020-10-27 16:28:18 +08:00
    @coderluan 怎么调,有相关的包吗
    coderluan
        4
    coderluan  
       2020-10-27 16:28:47 +08:00
    @James369 自己搜去, 一搜一堆.
    jdhao
        5
    jdhao  
       2020-10-27 16:31:55 +08:00 via Android
    你具体什么问题?如果是 io 密集型操作,用 asyncio 或者 threadpoolexecutor 做并发不一定慢,干嘛非得多线程。

    或者 cpu 密集操作,多进程做也没问题。
    chaleaoch
        6
    chaleaoch  
       2020-10-27 16:46:33 +08:00
    重 CPU 任务是指计算密集吗?
    计算密集你用 python?

    node 主线程确实是单线程, 不过 Node 本身自己都承认擅长 IO 不擅长 CPU 计算.

    不知道吐槽点在哪里.
    em70
        7
    em70  
       2020-10-27 16:48:27 +08:00
    我经常 20 个 python 进程跑满 CPU 的,写在一个进程里还麻烦
    GrayXu
        8
    GrayXu  
       2020-10-27 16:55:39 +08:00
    为什么不好好用搜索引擎呢?

    import multiprocessing
    est
        9
    est  
       2020-10-27 16:56:28 +08:00
    LZ 恐怕也没听说过几个能用系统内核线程的语言。。。
    oahebky
        10
    oahebky  
       2020-10-27 17:00:04 +08:00 via Android   1
    其实 Python 的多进程和多线程差不多好写;

    如果你线程间传递数据要考虑加锁,
    而进程间传递数据涉及到进程间通信(但是 Python 的库已经封装好了,很容易调用传递数据)

    也就是说,你要“并行执行”,其实在 Python 中写线程和进程几乎没有差别。

    如果你涉及到并行执行的“东西”要传递数据,只是把线程加锁的思考换成进程间通信的思考,也差不多。


    然后如果是那种用 queue 发消息的传递数据类型,在 Python 中进程和线程的写法也是非常像...


    所以问题不在于 GIL,

    问题在于:
    1. programmer 是否理解并发和并行
    2. 是否理解 IO 密集和 CPU 密集
    3. 是否知道 Python 有 GIL 这个东西
    4. programmer 掌握的并发编程「模型」的水平。


    而其它语言(比如 golang )好写并发代码(多线程),应该是人家已经给你限定好了一种并发模型,让“入门者”的就照着这么写就好了(恩,我没用过 golang,但是我猜是 golang 这样子的,有不对欢迎指正)。
        11
    leavic  
       2020-10-27 17:06:35 +08:00
    所以我直接多进程不就行了
    leavic
    oahebky
        12
    oahebky  
       2020-10-27 17:07:02 +08:00
    对了 “问题在于:” 还要再插入一个点,

    “3. 是否理解‘线程内存(变量)共享’ 和 ‘进程内存拷贝’ 之间的区别”。
    xiaoshenke
        13
    xiaoshenke  
       2020-10-27 17:12:04 +08:00 via Android
    @oahebky 好不好写不关键。进程耗 cpu 。java 来实现开 20 个线程,py 就需要 20 个进程,高下立判
    oahebky
        14
    oahebky  
       2020-10-27 17:25:40 +08:00
    @xiaoshenke

    你的这种比较在选择了脚本语言 /动态语言的程序员眼里没有意义。

    至少在我这边没有意义。

    如果说别的语言并行比较好写,我会觉得是优点。

    但是如果说别的语言多线程利用 CPU 比 Python 多进程利用 CPU “效率”更高,在我这边没有意义。


    因为就是有像我这类开发者并不关心一门语言在机器上的执行速度,而是编程语言的其它方面。


    (当然,根据应用的业务场景,语言在机器上的执行速度可能是重要的,
    但这是针对业务的技术选型问题,不是编程语言本身的问题;
    就像用锤子去敲螺丝,这不是锤子的问题,这是你选择锤子还是选择螺丝刀的问题。)
    kkbblzq
        15
    kkbblzq  
       2020-10-27 17:26:31 +08:00
    @xiaoshenke 所以才说要确定你的业务是不是 CPU 密集型的,调度这块的确线程有优势,但是你长期占满不需要调度的情况下差距就小了
    ai277014717
        16
    ai277014717  
       2020-10-27 17:30:21 +08:00
    可以用支持利用多核的语言来写然后封装成 cli 或者 libc 来调用。推荐 cli crash 了不会影响父进程。
    xiaoshenke
        17
    xiaoshenke  
       2020-10-27 17:34:57 +08:00 via Android
    @oahebky 同理 你在比较语言好不好写在我这里也没有意义
    chogath
        18
    chogath  
       2020-10-27 17:36:40 +08:00
    CPU 核心的同时利用还是得用 C,另外 node.js 其实可以使用 worker_threads 模块开启多线程,不过要处理数据共享,我的方案是任务启动前先写入公共 JSON 文件中,线程任务独立地读取 JSON 文件内的数据 /配置并执行任务
    acmore
        19
    acmore  
       2020-10-27 18:06:37 +08:00
    无论多线程多进程协程纤程,本质都是为了提升 CPU 的利用率。如果你要处理的任务是 I/O 密集型的,那么直接用 Python 协程就好了,效率很有可能比多线程或者多进程更高。如果你要处理的任务是计算密集型的,那么 Python 多进程 / C 扩展多线程是更好的选择,当然最好的选择是用其他语言。

    另外 JS 是单线程 ≠ JS 只能利用一丢丢计算资源,这里的单线程确切来说是用户能直接操作的是单线程。无论在浏览器还是在 Node 平台上,背后都有一堆工作线程在做事。能最大限度利用资源才是直接和最终的目标。
    Meltdown
        20
    Meltdown  
       2020-10-27 19:05:59 +08:00 via Android
    经常看到你不一定需要真正的多线程这种回答就感觉好窝火
    nightwitch
        21
    nightwitch  
       2020-10-27 19:27:59 +08:00
    @xiaoshenke 看平台的,在 Linux 下线程和进程的开销基本是相同的,都是一个 task_struct 。
    ivi
        22
    ivi  
       2020-10-28 14:43:56 +08:00
    LZ,想问下多线程=并发执行这个有什么问题吗?
    xiaoshenke
        23
    xiaoshenke  
       2020-10-28 14:48:45 +08:00 via Android
    @nightwitch ??????怎么可能
    maxxfire
        24
    maxxfire  
       2020-10-28 14:58:50 +08:00
    @ivi python 中的多线程,实质上是单 CPU 执行,非并发操作。因为有个全局锁在同步。
    fasionchan
        25
    fasionchan  
       2020-10-29 08:12:52 +08:00
    关于 GIL 的由来、Python 虚拟机线程调度、IO 密集型以及计算密集型程序区别、以及如何绕过 GIL 取得多核心利用能力这些话题,可以参考这篇文章:

    https://mp.weixin.qq.com/s/lIkcTuCX5htQcteklCFaZw
    no1xsyzy
        26
    no1xsyzy  
       2020-10-29 14:49:09 +08:00
    @xiaoshenke 你对线程和进程关系理解错误。
    进程就是内核独立配给资源的线程,线程就是共享部分资源的进程,两者在 CPU 密集运算上没有区别。
    之前还有 IPC 的问题,但现在还有 shared_memory,区别更加模糊
    no1xsyzy
        27
    no1xsyzy  
       2020-10-29 14:53:15 +08:00
    lz 你是没分清并发( concurrency )和并行( parallel )……
    多线程 = 并发几乎是对的 除非你强行用 PC 锁,这个操作既麻烦又难以理解,但我确实可以开五个线程,并且通过锁和队列来强制严格的执行顺序。
    xiaoshenke
        28
    xiaoshenke  
       2020-10-29 19:35:13 +08:00 via Android
    @no1xsyzy 合着起进程不需要有拷贝母进程分配进程资源的过程了。我看你是读书读傻了
    no1xsyzy
        29
    no1xsyzy  
       2020-10-29 21:54:16 +08:00   1
    @xiaoshenke copy on write 啊……
    20 个进程除了污染 ps 列表和需要 IPC 以外没什么毛病
    而且 20 个线程依然有上下文切换和缓存未命中的问题,GC 更是几百倍消耗。
    你这么说不如直接 C / C++ / Rust,Java 算个雕?
    fasionchan
        30
    fasionchan  
       2020-10-30 13:29:33 +08:00
    @no1xsyzy 真要细说进程和线程的差别,页表应该算一个。同个进程内的线程切换,不需要切页表;但不同进程切换需要切页表,刷 TLB,性能点差别。不过话说回来,如果对这点性能都敏感,还用啥 Python ……
    no1xsyzy
        31
    no1xsyzy  
       2020-11-02 01:39:24 +08:00
    @fasionchan …… 话说一般是分在多核心上的吧,页表切换实际影响的是 L3 缓存?而且一不小心可能分到多个 CCX 上去……
    要充分享受 CPU 缓存干脆连带厚重运行时的 Python Java C# 都 pass,缓存脱靶太常见了,一个 call 基本就要脱靶了。
    所以并行计算就应该用函数式写(突然暴论
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2659 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 31ms UTC 07:50 PVG 15:50 LAX 23:50 JFK 02:50
    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