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 · 5536 次点击
    这是一个创建于 1478 天前的主题,其中的信息可能已经有所发展或是发生改变。
    貌似 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 这样子的,有不对欢迎指正)。
    leavic
        11
    leavic  
       2020-10-27 17:06:35 +08:00
    所以我直接多进程不就行了
    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   ·   实用小工具   ·   5846 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 33ms · UTC 03:01 · PVG 11:01 · LAX 19:01 · JFK 22:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.