Python 如何避免线程间的全局锁 GIL 进行并行计算?

2020-10-06 10:20:56 +08:00
 threebr

我现在有一个串行的代码,长这样:

for t in range(100000):
    A(t+1) = fun_A(B(t))
    B(t+1) = fun_B(A(t))

fun_A(), fun_B() 是我自己写的两个函数,分别需要上一个循环中对方的输出作为输入。

现在有没有办法将 fun_A(), fun_B() 在一个循环内并行执行?用多线程的话因为 CPython 存在全局锁可能实际上是串行执行,多进程的话不知道会不会额外增加两个函数间的数据传递的 I/O 开销。

各位有没有什么其他实现的思路?

2577 次点击
所在节点    问与答
23 条回复
SingeeKing
2020-10-06 10:34:47 +08:00
这是典型的用 Python 必有额外开销的问题。换语言吧
wander639
2020-10-06 10:49:20 +08:00
用 go 实现吧
threebr
2020-10-06 11:09:35 +08:00
@SingeeKing
@wander639

换语言我个人的时间成本太高了,效果也难以估计,只能是最后的办法
laike9m
2020-10-06 11:14:18 +08:00
A(t+1) 这个语法没看懂,你是想写中括号?
BiteTheDust
2020-10-06 11:16:15 +08:00
A(t)->B(t+1)->A(t+2)->B(t+3)....
B(t)->A(t+1).....
这两个直接分开多进程执行如何呢
laike9m
2020-10-06 11:16:33 +08:00
如果是中括号的话,你这个就是没法并行,换什么语言都没用。我能想到的优化就是 lru 一下 A 和 B,避免对相同参数重复计算
threebr
2020-10-06 11:23:13 +08:00
@laike9m 是中括号,只在单个循环内部还是可以把两个函数改成并行的
whenov
2020-10-06 11:26:54 +08:00
你画出来流程就会发现是两条不重合的计算链,用两个进程分别计算即可。计算过程中无需共享数据,结束后交换两个数组的偶数位。
makdon
2020-10-06 11:28:53 +08:00
如果 func_A 或 B 内涉及外部 IO 例如网络等,这俩并行的话还是可以提高那么一丢丢性能的,不过在这个 case 里面个人更倾向于优化 func_A 和 func_B 的性能为主,可以先做下 benchmark 看看瓶颈在哪
youngce
2020-10-06 11:34:57 +08:00
实际上对整体性能的提升不会太大的。写 python 太多新手,一不做性能分析,二不做测试,自己不小心写出一堆阻塞逻辑,最后怪 python 慢。实际上为什么 go 这么火,一定程度也是因为可以让菜鸟轻松写出性能不错的代码
Wicked
2020-10-06 11:56:06 +08:00
从顶楼的代码看不适合并行,每一次循环都依赖来自另外一条线的输出。另外,Python 优先考虑多进程。
lpts007
2020-10-06 12:01:12 +08:00
如果想改并行,说明慢,慢说明是 python 问题,那么改成 go 问题就消失了。

请 python 新手谨遵以上原则
imn1
2020-10-06 12:03:39 +08:00
看样子很适合 pandas 的 rolling 函数(移动计算)
lxy42
2020-10-06 12:07:14 +08:00
把计算流程展开你就会发现:A[n] = fun_A(B[n - 1]) = fun_A(fun_B(A[n - 2])),A 的计算其实和 B 没有太大关系。
yangxin0
2020-10-06 12:45:56 +08:00
写 python 扩展,在 c/c++里面就没有 GIL 了
huskar
2020-10-06 22:40:11 +08:00
这和 GIL 有啥关系啊……纯粹是楼主自己没想明白,像楼上说的拆成两个序列分别算就好。
各位说换语言、换 go 、写 c 的亮下代码?想知道怎么写能满足楼主需求。
black11black
2020-10-06 22:47:32 +08:00
@huskar 他的意思是我用多线程,就遇到 GIL 的问题,所以如果不愿意换语言,一般来说解决方法开销从低到高有:1 、换 JIT 解释器 2 、多进程 3 、用魔法 JIT 搞定一些计算密集部分 4 、计算密集部分用 cython 替代
sunhk25
2020-10-07 07:56:44 +08:00
sunhk25
2020-10-07 07:58:29 +08:00
线程的话开销比会很大吗
sunhk25
2020-10-07 07:58:47 +08:00
@sunhk25 进程

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/712727

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX