繁体   English   中英

Python 主模块外的多处理:计算缓慢

[英]Python multiprocessing outside main module: slow computations

我有一个代码,旨在在不是 main.py 的某个模块的某个内部部分进行多处理。 为简单起见,我创建了一个包含两个文件的副本代码:main.py 和文件 f1_mod.py。 我的 main.py 看起来像:

import os
from time import time
import f1_mod

parallel = 1
N = 10000000

if __name__ == '__main__':  

    if not parallel:
        time_start = time()
        res = f1_mod.normal_exec( N )
        time_end =  time()
    
        print("-->time is ", time_end - time_start )
    else:
        time_start = time()
        res = f1_mod.parallel_exec( N )
        time_end =  time()
    
        print("-->time is ", time_end - time_start )

    for j in range( 100 ):
        print( res[j] )

    else:  
        print("--> CHILD PROCESS ID: ", os.getpid() )
        pass

f1_mod.py 将是:

import multiprocessing as mp
import numpy as np


def pool_worker_function( k, args ):    
    d = args[0]        
    return d["p"]*( k**2 ) + d["x"]**2     
        
def single_thread_exec( N ):    
    a = list( np.linspace( 0, N, N ) )    
    d = { "p": 0.2, "x": 0.5 } 
    result =  []    
    for k in a:        
        result.append( d["p"]*( k**2) + d["x"]**2 )
    return result

def parallel_exec( N ):
    number_processors      = mp.cpu_count()
    number_used_processors = number_processors - 1

    #try pool map method            
    from itertools import repeat      

    pool    = mp.Pool( processes = number_used_processors )   

    d = { "p": 0.2, "x": 0.5 } 
    a = list( np.linspace( 0, N, N ) )          
    
    args = ( d, )     
    number_tasks = number_used_processors              

    chuncks = []    
    n_chunck = int( ( len(a) - 1 )/number_tasks )
    for j in range( 0, number_tasks ):
    
        if ( j == number_tasks - 1 ):
            chuncks.append( a[ j*n_chunck: ] )
        else:
            chuncks.append( a[ j*n_chunck: j*n_chunck + n_chunck ]   ) 
      
    result = pool.starmap( pool_worker_function, zip( a, repeat( args ) ) )              
    pool.close()        
    pool.join()           
    return result

我检查了串行版本和并行版本都给出了相同的结果,除了串行版本比多处理版本快得多 在我的真实代码中,有时会出现这种情况,进入 worker function 的“args”元组实际上包含一个大的 object 数据容器,其中包含一个更大的字典,用于从中读取数据以执行操作。 谁能解释为什么我会观察到这种行为(即多处理时性能缓慢)? 每次都需要将数据传递给工作人员 function ,实际上这使得工作人员 function 占用了大量 arguments 可能是什么减缓了 IPC 代码给出的地方? (¿?)

使用传递给工作人员的参数中的“重复”,因为元组传递的所有 arguments 对于每个工作人员都必须相同,唯一可迭代的是列表“a”。 有谁知道如何对此进行有效的多处理? 另外,请注意,多处理不会发生在“main.py”级别,而是发生在代码逻辑中某些模块的“深层”函数中。 我希望能得到一些帮助,以更好地理解这种多处理是如何工作的,我在 Windows 操作系统下使用 4 核机器。 我现在知道 Windows 在使用多处理时不支持类似“fork”的行为,但是,在我的机器上运行 Ubuntu 中的代码似乎也很慢! 谢谢!!

我对当前代码的最佳猜测:您在pool_worker_function中没有做足够的工作来抵消通信/同步的成本。

我可能错了,但是您的代码似乎完成了一半:从未使用过chunks变量。 无论如何,传递一个大的 arrays (你的块)可能不是最好的解决方案。

您可以尝试将 start/len 参数传递给您的pool_worker_function ,然后创建数组并在那里进行计算,但我不能 100% 确定它是否足以抵消结果的通信成本。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM