2016-08-24 96 views
2

所以我試圖在python中實現多處理,我希望有一個4-5進程池並行運行一個方法。這樣做的目的是運行總共1000次蒙特卡洛模擬(每個進程250-200次模擬),而不是運行1000次。我希望每個進程都能夠在完成處理後立即獲取鎖,從而寫入共享共享數組結果爲一個模擬,寫結果並釋放鎖。因此,它應該是三個步驟:多處理 - 共享陣列

  1. 採集鎖
  2. 寫結果
  3. 等待寫入到陣列的其他進程釋放鎖。

每次我將數組傳遞給進程時,每個進程都會創建該數組的副本,我不想要這個數組的副本,因爲我想要一個常用數組。任何人都可以通過提供示例代碼來幫助我?

+0

如果你搜索一些答案,你有大量的示例代碼。 因此,如果你不提供你的一些,我們將無法幫助你。 順便說一下,使用[semaphores](https://docs.python.org/2/library/threading.html#semaphore-objects)來鎖定線程 – Raskayu

+0

關於[示例]有什麼不清楚的地方(https://docs.python .org/3/library/multiprocessing.html#sharing-state-between-processes)在官方文檔中? – mata

+0

您在模擬進行中時是否需要訪問陣列?如果沒有,你可以使用一組'Pool.map'函數。 – Dunes

回答

0

未測試,但類似的東西應該工作。 數組和鎖在進程之間共享。

from multiprocessing import Process 

def f(array,lock): 
    lock.acquire() 
    #modify array here 
    lock.release() 

if __name__ == '__main__': 
    size=100 
    multiprocessing.Array('i', size) #c type array 
    lock=multiprocessing.Lock() 
    p = Process(target=f, args=(arr,lock,)) 
    q = Process(target=f, args=(arr,lock,)) 
    p.start() 
    q.start() 
    q.join() 
    p.join() 

文檔這裏https://docs.python.org/3.5/library/multiprocessing.html有大量的實例入手

+0

這不是一個共享數組。在子流程中更改它不會對父級有任何影響。 – mata

+0

@mata更正了共享數組 – Julien

+2

另外,默認情況下會創建一個[Array](https://docs.python.org/3/library/multiprocessing.html#multiprocessing.Array),並附加一個鎖,您可以使用它它的'get_lock()'方法,除非你想使用不同的鎖類型,否則不需要明確地分配它。然後,body可以成爲'array.get_lock():'' – mata

0

既然你只能從子進程返回狀態的父進程,然後使用一個共享的陣列,並且明確地鎖是矯枉過正。您可以使用Pool.mapPool.starmap來完成您需要的功能。例如:

from multiprocessing import Pool 

class Adder: 
    """I'm using this class in place of a monte carlo simulator""" 

    def add(self, a, b): 
     return a + b 

def setup(x, y, z): 
    """Sets up the worker processes of the pool. 
    Here, x, y, and z would be your global settings. They are only included 
    as an example of how to pass args to setup. In this program they would 
    be "some arg", "another" and 2 
    """ 
    global adder 
    adder = Adder() 

def job(a, b): 
    """wrapper function to start the job in the child process""" 
    return adder.add(a, b) 

if __name__ == "__main__": 
    args = list(zip(range(10), range(10, 20))) 
    # args == [(0, 10), (1, 11), ..., (8, 18), (9, 19)] 

    with Pool(initializer=setup, initargs=["some arg", "another", 2]) as pool: 
     # runs jobs in parallel and returns when all are complete 
     results = pool.starmap(job, args) 

    print(results) # prints [10, 12, ..., 26, 28]