2016-08-24 93 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]