Python中的动态过程

时间:2009-04-11 20:15:47

标签: python multithreading multiprocessing

我有一个关于Python多处理的问题。我试图获取一个数据集,分成几个块,然后将这些块传递给并发运行的进程。我需要使用简单的计算来转换大型数据表(例如,电阻 - >热敏电阻的温度)。

下面列出的代码几乎可以按预期工作,但它似乎不会产生任何新进程(或者如果一次只有一个进程)。我是Python的新手,所以对这个问题可能有一个非常简单的解决方案。

提前致谢!

from multiprocessing import Process

class Worker(Process):
    # example data transform
    def process(self, x): return (x * 2) / 3

    def __init__(self, list):
        self.data = list
        self.result = map(self.process, self.data)
        super(Worker, self).__init__()

if __name__ == '__main__':
    start = datetime.datetime.now()
    dataset = range(10000) # null dataset
    processes = 3

    for i in range(processes):
        chunk = int(math.floor(len(dataset) / float(processes)))

        if i + 1 == processes:
            remainder = len(dataset) % processes
        else: remainder = 0

        tmp = dataset[i * chunk : (i + 1) * chunk + remainder]
        exec('worker'+str(i)+' = Worker(tmp)')
        exec('worker'+str(i)+'.start()')

    for i in range(processes):
        exec('worker'+str(i)+'.join()')
        # just a placeholder to make sure the initial values of the set are as expected
        exec('print worker'+str(i)+'.result[0]')

3 个答案:

答案 0 :(得分:1)

您尚未覆盖run方法。进程(或线程)有两种方法可以让它执行代码:

  1. 创建指定目标
  2. 的流程
  3. 对流程进行子类化,覆盖run方法。
  4. 覆盖__init__只意味着您的流程无处可去。它应该用于为它提供执行所需执行的属性,但不应指定要执行的任务。

    在你的代码中,所有繁重的工作都在这一行完成:

    exec('worker'+str(i)+' = Worker(tmp)')
    

    这里没有做任何事情:

    exec('worker'+str(i)+'.start()')
    

    因此,使用exec('print worker'+str(i)+'.result[0]')检查结果应该会给你一些有意义的东西,但这只是因为你想要执行的代码已经执行了,但是在流程构建上,而不是在流程启动时。

    试试这个:

    class Worker(Process):
        # example data transform
        def process(self, x): return (x * 2) / 3
    
        def __init__(self, list):
            self.data = list
            self.result = []
            super(Worker, self).__init__()
    
        def run(self):
            self.result = map(self.process, self.data)
    

    编辑:

    好吧......所以我只是根据我的线程本能飞行,他们都错了。我们都不了解流程的是你无法直接共享变量。无论您传递给新流程的是什么,都会被阅读,复制并永远消失。除非您使用两种标准方式之一来共享数据:queues and pipes。我玩了一下试图让你的代码工作,但到目前为止没有运气。我想这会让你走上正轨。

答案 1 :(得分:1)

无需向每个进程发送块数,只需使用get_nowait()并处理最终的Queue.Empty异常。每个进程都会获得不同的CPU时间,这应该让他们都忙着。

import multiprocessing, Queue

class Worker(multiprocessing.Process):
    def process(self, x): 
        for i in range(15):
            x += (float(i) / 2.6)
        return x

    def __init__(self, input, output):
        self.input = input
        self.output = output
        super(Worker, self).__init__()

    def run(self):
        try:
            while True:
                self.output.put(self.process(self.input.get_nowait()))
        except Queue.Empty:
            pass


if name == 'main':
    dataset = range(10)
    processes = multiprocessing.cpu_count()
    input = multiprocessing.Queue()
    output = multiprocessing.Queue()

    for obj in dataset:
        input.put(obj)
    for i in range(processes):
        Worker(input, output).start()

    for i in range(len(dataset)):
        print output.get()

答案 2 :(得分:0)

好的,所以看起来这个列表不是线程安全的,我已经开始使用Queue了(尽管看起来要慢很多)。这段代码基本上完成了我想要做的事情:

import math, multiprocessing

class Worker(multiprocessing.Process):
    def process(self, x): 
        for i in range(15):
            x += (float(i) / 2.6)
        return x

    def __init__(self, input, output, chunksize):
        self.input = input
        self.output = output
        self.chunksize = chunksize
        super(Worker, self).__init__()

    def run(self):
        for x in range(self.chunksize):
            self.output.put(self.process(self.input.get()))


if __name__ == '__main__':
    dataset = range(10)
    processes = multiprocessing.cpu_count()
    input = multiprocessing.Queue()
    output = multiprocessing.Queue()

    for obj in dataset:
        input.put(obj)

    for i in range(processes):
        chunk = int(math.floor(len(dataset) / float(processes)))
        if i + 1 == processes:
            remainder = len(dataset) % processes
        else: remainder = 0

        Worker(input, output, chunk + remainder).start()

    for i in range(len(dataset)):
        print output.get()