簡體   English   中英

在Python中使用池進行多處理(Windows)

[英]Using pool for multiprocessing in Python (Windows)

我必須以平行的方式進行學習,以便更快地運行它。 我是python中多處理庫的新手,還不能使它成功運行。 在這里,我正在調查每對(起源,目標)是否仍然在我研究的各個幀之間的某些位置。 幾點:

  1. 這是一個功能,我想要更快地運行(這不是幾個過程)。
  2. 該過程隨后進行; 這意味着每一幀都與前一幀進行比較。
  3. 此代碼是原始代碼的一種非常簡單的形式。 代碼輸出一個residece_list。
  4. 我正在使用Windows操作系統。

有人可以檢查代碼(多處理部分)並幫助我改進它以使其工作。 謝謝。

import numpy as np
from multiprocessing import Pool, freeze_support


def Main_Residence(total_frames, origin_list, target_list):
    Previous_List = {}
    residence_list = []

    for frame in range(total_frames):     #Each frame

        Current_List = {}               #Dict of pair and their residence for frames
        for origin in range(origin_list):

            for target in range(target_list):
                Pair = (origin, target)         #Eahc pair

                if Pair in Current_List.keys():     #If already considered, continue
                    continue
                else:
                    if origin == target:
                        if (Pair in Previous_List.keys()):            #If remained from the previous frame, add residence
                            print "Origin_Target remained: ", Pair
                            Current_List[Pair] = (Previous_List[Pair] + 1)
                        else:                                           #If new, add it to the current
                            Current_List[Pair] = 1

        for pair in Previous_List.keys():                        #Add those that exited from residence to the list
            if pair not in Current_List.keys():
                residence_list.append(Previous_List[pair])

        Previous_List = Current_List
    return residence_list

if __name__ == '__main__':
    pool = Pool(processes=5)
    Residence_List = pool.apply_async(Main_Residence, args=(20, 50, 50))
    print Residence_List.get(timeout=1)
    pool.close()
    pool.join()
    freeze_support()

Residence_List = np.array(Residence_List) * 5

多處理在您在此處呈現的上下文中沒有意義。 您正在創作5個子過程(以及屬於池,管理人員,任務和結果三個線程)執行一次 一個功能。 所有這些都需要花費在系統資源和執行時間上,而你的四個工作流程根本不做任何事情。 多處理不會加速函數的執行。 特定示例中的代碼總是比在主進程中明確執行Main_Residence(20, 50, 50)慢。

要使多處理在這樣的上下文中有意義,您的工作需要分解為一組可以並行處理的同質任務,其結果可能在以后合並。

作為示例(不一定是好的),如果要計算一系列數字的最大素數因子,可以將計算任何特定數字的因子的任務委派給池中的工作者。 然后,幾個工人將並行進行這些單獨的計算:

def largest_prime_factor(n):
    p = n
    i = 2
    while i * i <= n:
        if n % i:
            i += 1
        else:
            n //= i
    return p, n


if __name__ == '__main__':
    pool = Pool(processes=3)
    start = datetime.now()
    # this delegates half a million individual tasks to the pool, i.e. 
    # largest_prime_factor(0), largest_prime_factor(1), ..., largest_prime_factor(499999)      
    pool.map(largest_prime_factor, range(500000))
    pool.close()
    pool.join()
    print "pool elapsed", datetime.now() - start
    start = datetime.now()
    # same work just in the main process
    [largest_prime_factor(i) for i in range(500000)]
    print "single elapsed", datetime.now() - start

輸出:

pool elapsed 0:00:04.664000
single elapsed 0:00:08.939000

(在這個答案中largest_prime_factor函數取自@Stefan

正如您所看到的,池的速度大約是單個進程執行相同工作量的兩倍,所有這些都是在三個並行的進程中運行的。 這是由於多處理/池引入的開銷。

所以,你說過你的例子中的代碼已經簡化了。 您必須分析原始代碼,看它是否可以分解為可以傳遞到池中進行處理的同質任務。 如果可以,使用多處理可能會幫助您加快程序的速度。 如果沒有,多處理可能會花費你的時間,而不是保存它。

編輯:
因為您詢問了有關代碼的建議。 我幾乎無法談論你的功能。 你自己說過這只是一個簡單的例子來提供一個MCVE(非常感謝順便說一句!大多數人都沒有花時間將代碼剝離到最低限度)。 無論如何,代碼審查的請求更適合Codereview

使用可用的任務委派方法稍微玩一下。 在我的素因子示例中,使用apply_async帶來巨大的懲罰。 與使用map相比,執行時間增加了九倍。 但我的例子是使用一個簡單的迭代,你的每個任務需要三個參數。 這可能是starmap一種情況,但這只能從Python 3.3開始提供。
無論如何,任務數據的結構/性質基本上決定了使用的正確方法。
我通過多處理您的示例函數進行了一些q&d測試。 輸入定義如下:

inp = [(20, 50, 50)] * 5000  # that makes 5000 tasks against your Main_Residence

我在Python 3.6中運行了三個子進程,你的函數沒有改變,除了刪除print聲明(I / O成本很高)。 我使用了starmapapplystarmap_asyncapply_async並且每次都會迭代結果,以解決異步結果上的阻塞get()問題。
這是輸出:

starmap elapsed 0:01:14.506600
apply elapsed 0:02:11.290600
starmap async elapsed 0:01:27.718800
apply async elapsed 0:01:12.571200
# btw: 5k calls to Main_Residence in the main process looks as bad 
# as using apply for delegation
single elapsed 0:02:12.476800

正如您所看到的,執行時間不同,盡管所有四種方法都執行相同的工作量; 您選擇的apply_async似乎是最快的方法。

編碼風格。 你的代碼看起來很......非常規:)你使用Capitalized_Words_With_Underscore作為你的名字(函數和變量名),這在Python中幾乎是禁忌。 此外,將名稱Previous_List分配給字典是......有問題的。 看一下PEP 8 ,特別是命名約定部分,看看Python普遍接受的編碼風格。

從你的print看起來的方式來看,你仍然在使用Python 2.我知道在公司或機構環境中,有時你可以使用它。 不過,請記住, Python 2時鍾正在滴答作響

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM