我现在有一个串行的代码,长这样:
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 开销。
各位有没有什么其他实现的思路?
     1 
                    
                    SingeeKing   PRO 这是典型的用 Python 必有额外开销的问题。换语言吧 
                 | 
            
     2 
                    
                    wander639      2020-10-06 10:49:20 +08:00 
                    
                    用 go 实现吧 
                 | 
            
     3 
                    
                    threebr   OP  | 
            
     4 
                    
                    laike9m      2020-10-06 11:14:18 +08:00 via Android 
                    
                    A(t+1) 这个语法没看懂,你是想写中括号? 
                 | 
            
     5 
                    
                    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)..... 这两个直接分开多进程执行如何呢  | 
            
     6 
                    
                    laike9m      2020-10-06 11:16:33 +08:00 via Android 
                    
                    如果是中括号的话,你这个就是没法并行,换什么语言都没用。我能想到的优化就是 lru 一下 A 和 B,避免对相同参数重复计算 
                 | 
            
     8 
                    
                    whenov      2020-10-06 11:26:54 +08:00 
                    
                    你画出来流程就会发现是两条不重合的计算链,用两个进程分别计算即可。计算过程中无需共享数据,结束后交换两个数组的偶数位。 
                 | 
            
     9 
                    
                    makdon      2020-10-06 11:28:53 +08:00    如果 func_A 或 B 内涉及外部 IO 例如网络等,这俩并行的话还是可以提高那么一丢丢性能的,不过在这个 case 里面个人更倾向于优化 func_A 和 func_B 的性能为主,可以先做下 benchmark 看看瓶颈在哪 
                 | 
            
     10 
                    
                    youngce      2020-10-06 11:34:57 +08:00    实际上对整体性能的提升不会太大的。写 python 太多新手,一不做性能分析,二不做测试,自己不小心写出一堆阻塞逻辑,最后怪 python 慢。实际上为什么 go 这么火,一定程度也是因为可以让菜鸟轻松写出性能不错的代码 
                 | 
            
     11 
                    
                    Wicked      2020-10-06 11:56:06 +08:00 via iPhone 
                    
                    从顶楼的代码看不适合并行,每一次循环都依赖来自另外一条线的输出。另外,Python 优先考虑多进程。 
                 | 
            
     12 
                    
                    lpts007      2020-10-06 12:01:12 +08:00 
                    
                    如果想改并行,说明慢,慢说明是 python 问题,那么改成 go 问题就消失了。 
                请 python 新手谨遵以上原则  | 
            
     13 
                    
                    imn1      2020-10-06 12:03:39 +08:00 
                    
                    看样子很适合 pandas 的 rolling 函数(移动计算) 
                 | 
            
     14 
                    
                    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 没有太大关系。 
                 | 
            
     15 
                    
                    yangxin0      2020-10-06 12:45:56 +08:00    写 python 扩展,在 c/c++里面就没有 GIL 了 
                 | 
            
     16 
                    
                    huskar      2020-10-06 22:40:11 +08:00 via Android 
                    
                    这和 GIL 有啥关系啊……纯粹是楼主自己没想明白,像楼上说的拆成两个序列分别算就好。 
                各位说换语言、换 go 、写 c 的亮下代码?想知道怎么写能满足楼主需求。  | 
            
     17 
                    
                    black11black      2020-10-06 22:47:32 +08:00    @huskar 他的意思是我用多线程,就遇到 GIL 的问题,所以如果不愿意换语言,一般来说解决方法开销从低到高有:1 、换 JIT 解释器 2 、多进程  3 、用魔法 JIT 搞定一些计算密集部分 4 、计算密集部分用 cython 替代 
                 | 
            
     19 
                    
                    sunhk25      2020-10-07 07:58:29 +08:00 via Android 
                    
                    线程的话开销比会很大吗 
                 | 
            
     21 
                    
                    threebr   OP @sunhk25 我还没有开始实践,只是网上的说法如此,线程比进程更轻量,切换线程的上下文开销和线程间数据同步的开销都比进程小 
                 | 
            
     22 
                    
                    huskar      2020-10-07 13:06:23 +08:00 via Android 
                    
                    @black11black 我是说楼主这需求跟 gil 没关系。比如用 c,没有 gil,该怎么写? 
                 | 
            
     23 
                    
                    black11black      2020-10-07 21:41:14 +08:00 
                    
                    @threebr 理论上线程也需要进行内核态切换,不像协程局限在用户态内,所以 asyncio 的出现极大地拓展了 py 的 IO 相关处理能力,和进程有多大差距应该是在内存部分,具体的没了解到非常详细的部分。但是线程切换是有切片时间的,比如一种情况是比如你计划在一秒内转换一万次线程,这种密度上使用多线程会导致效率降低很多 
                 |