簡體   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