1
coderluan 2020-10-27 15:15:19 +08:00
调 C 的多线程就行, 不要用多进程
|
2
coderxy 2020-10-27 16:03:28 +08:00
nodejs 就是无法利用多核心,所以会起多个进程。 不过现在很多都是 k8s 环境下,单个 pod 只利用单核心也没毛病。
|
5
jdhao 2020-10-27 16:31:55 +08:00 via Android
你具体什么问题?如果是 io 密集型操作,用 asyncio 或者 threadpoolexecutor 做并发不一定慢,干嘛非得多线程。
或者 cpu 密集操作,多进程做也没问题。 |
6
chaleaoch 2020-10-27 16:46:33 +08:00
重 CPU 任务是指计算密集吗?
计算密集你用 python? node 主线程确实是单线程, 不过 Node 本身自己都承认擅长 IO 不擅长 CPU 计算. 不知道吐槽点在哪里. |
7
em70 2020-10-27 16:48:27 +08:00
我经常 20 个 python 进程跑满 CPU 的,写在一个进程里还麻烦
|
8
GrayXu 2020-10-27 16:55:39 +08:00
为什么不好好用搜索引擎呢?
import multiprocessing |
9
est 2020-10-27 16:56:28 +08:00
LZ 恐怕也没听说过几个能用系统内核线程的语言。。。
|
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
所以我直接多进程不就行了
|
12
oahebky 2020-10-27 17:07:02 +08:00
对了 “问题在于:” 还要再插入一个点,
“3. 是否理解‘线程内存(变量)共享’ 和 ‘进程内存拷贝’ 之间的区别”。 |
13
xiaoshenke 2020-10-27 17:12:04 +08:00 via Android
@oahebky 好不好写不关键。进程耗 cpu 。java 来实现开 20 个线程,py 就需要 20 个进程,高下立判
|
14
oahebky 2020-10-27 17:25:40 +08:00
@xiaoshenke
你的这种比较在选择了脚本语言 /动态语言的程序员眼里没有意义。 至少在我这边没有意义。 如果说别的语言并行比较好写,我会觉得是优点。 但是如果说别的语言多线程利用 CPU 比 Python 多进程利用 CPU “效率”更高,在我这边没有意义。 因为就是有像我这类开发者并不关心一门语言在机器上的执行速度,而是编程语言的其它方面。 (当然,根据应用的业务场景,语言在机器上的执行速度可能是重要的, 但这是针对业务的技术选型问题,不是编程语言本身的问题; 就像用锤子去敲螺丝,这不是锤子的问题,这是你选择锤子还是选择螺丝刀的问题。) |
15
kkbblzq 2020-10-27 17:26:31 +08:00
@xiaoshenke 所以才说要确定你的业务是不是 CPU 密集型的,调度这块的确线程有优势,但是你长期占满不需要调度的情况下差距就小了
|
16
ai277014717 2020-10-27 17:30:21 +08:00
可以用支持利用多核的语言来写然后封装成 cli 或者 libc 来调用。推荐 cli crash 了不会影响父进程。
|
17
xiaoshenke 2020-10-27 17:34:57 +08:00 via Android
@oahebky 同理 你在比较语言好不好写在我这里也没有意义
|
18
chogath 2020-10-27 17:36:40 +08:00
CPU 核心的同时利用还是得用 C,另外 node.js 其实可以使用 worker_threads 模块开启多线程,不过要处理数据共享,我的方案是任务启动前先写入公共 JSON 文件中,线程任务独立地读取 JSON 文件内的数据 /配置并执行任务
|
19
acmore 2020-10-27 18:06:37 +08:00
无论多线程多进程协程纤程,本质都是为了提升 CPU 的利用率。如果你要处理的任务是 I/O 密集型的,那么直接用 Python 协程就好了,效率很有可能比多线程或者多进程更高。如果你要处理的任务是计算密集型的,那么 Python 多进程 / C 扩展多线程是更好的选择,当然最好的选择是用其他语言。
另外 JS 是单线程 ≠ JS 只能利用一丢丢计算资源,这里的单线程确切来说是用户能直接操作的是单线程。无论在浏览器还是在 Node 平台上,背后都有一堆工作线程在做事。能最大限度利用资源才是直接和最终的目标。 |
20
Meltdown 2020-10-27 19:05:59 +08:00 via Android
经常看到你不一定需要真正的多线程这种回答就感觉好窝火🔥
|
21
nightwitch 2020-10-27 19:27:59 +08:00
@xiaoshenke 看平台的,在 Linux 下线程和进程的开销基本是相同的,都是一个 task_struct 。
|
22
ivi 2020-10-28 14:43:56 +08:00
LZ,想问下多线程=并发执行这个有什么问题吗?
|
23
xiaoshenke 2020-10-28 14:48:45 +08:00 via Android
@nightwitch ??????怎么可能
|
25
fasionchan 2020-10-29 08:12:52 +08:00
关于 GIL 的由来、Python 虚拟机线程调度、IO 密集型以及计算密集型程序区别、以及如何绕过 GIL 取得多核心利用能力这些话题,可以参考这篇文章:
https://mp.weixin.qq.com/s/lIkcTuCX5htQcteklCFaZw |
26
no1xsyzy 2020-10-29 14:49:09 +08:00
@xiaoshenke 你对线程和进程关系理解错误。
进程就是内核独立配给资源的线程,线程就是共享部分资源的进程,两者在 CPU 密集运算上没有区别。 之前还有 IPC 的问题,但现在还有 shared_memory,区别更加模糊 |
27
no1xsyzy 2020-10-29 14:53:15 +08:00
lz 你是没分清并发( concurrency )和并行( parallel )……
多线程 = 并发几乎是对的 —— 除非你强行用 PC 锁,这个操作既麻烦又难以理解,但我确实可以开五个线程,并且通过锁和队列来强制严格的执行顺序。 |
28
xiaoshenke 2020-10-29 19:35:13 +08:00 via Android
@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 算个雕? |
30
fasionchan 2020-10-30 13:29:33 +08:00
@no1xsyzy 真要细说进程和线程的差别,页表应该算一个。同个进程内的线程切换,不需要切页表;但不同进程切换需要切页表,刷 TLB,性能点差别。不过话说回来,如果对这点性能都敏感,还用啥 Python ……
|
31
no1xsyzy 2020-11-02 01:39:24 +08:00
@fasionchan …… 话说一般是分在多核心上的吧,页表切换实际影响的是 L3 缓存?而且一不小心可能分到多个 CCX 上去……
要充分享受 CPU 缓存干脆连带厚重运行时的 Python Java C# 都 pass,缓存脱靶太常见了,一个 call 基本就要脱靶了。 所以并行计算就应该用函数式写(突然暴论 |