16

有没有一种简单的方法可以使用 Multiprocessing 来做同样的事情?

for sim in sim_list:
  sim.run()

其中 sim_list 的元素是“模拟”对象,而 run() 是模拟类的一个方法,它确实修改了对象的属性。例如:

class simulation:
    def __init__(self):
        self.state['done']=False
        self.cmd="program"
    def run(self):
        subprocess.call(self.cmd)
        self.state['done']=True

sim_list 中的所有 sim 都是独立的,因此该策略不必是线程安全的。

我尝试了以下,这显然是有缺陷的,因为参数是由 deepcopy 传递的,并且没有就地修改。

from multiprocessing import Process

for sim in sim_list:
  b = Process(target=simulation.run, args=[sim])
  b.start()
  b.join()
4

2 回答 2

15

做你想做的事情的一种方法是让你的计算类(simulation在你的情况下)成为Process. 正确初始化后,此类的实例将在单独的进程中运行,您可以按照您的需要从列表中设置一组实例。

这是一个示例,基于您上面写的内容:

import multiprocessing
import os
import random

class simulation(multiprocessing.Process):
    def __init__(self, name):
        # must call this before anything else
        multiprocessing.Process.__init__(self)

        # then any other initialization
        self.name = name
        self.number = 0.0
        sys.stdout.write('[%s] created: %f\n' % (self.name, self.number))

    def run(self):
        sys.stdout.write('[%s] running ...  process id: %s\n' 
                         % (self.name, os.getpid()))

        self.number = random.uniform(0.0, 10.0)
        sys.stdout.write('[%s] completed: %f\n' % (self.name, self.number))

然后只需制作一个对象列表并以循环开始每个对象:

sim_list = []
sim_list.append(simulation('foo'))
sim_list.append(simulation('bar'))

for sim in sim_list:
    sim.start()

当您运行它时,您应该看到每个对象都在其自己的进程中运行。不要忘记Process.__init__(self)在你的类初始化中首先调用,然后再调用。

显然,在这个例子中我没有包含任何进程间通信。如果您的情况需要,您必须添加它(从您的问题中不清楚您是否需要它)。

这种方法对我很有效,我不知道有任何缺点。如果有人知道我忽略的隐患,请告诉我。

我希望这有帮助。

于 2013-04-24T21:19:53.180 回答
2

对于那些将使用大型数据集的人来说,这iterable将是您的解决方案:

import multiprocessing as mp
pool = mp.Pool(mp.cpu_count())
pool.imap(sim.start, sim_list)
于 2019-08-14T06:24:55.593 回答