并行处理 - 池 - Python

时间:2013-10-17 14:23:43

标签: python parallel-processing multiprocessing pool

我正在尝试学习如何在Python中使用多处理。 我读到了multiprocessing,我试图做这样的事情:

我有以下类(部分代码),它有一个生成voronoi图的方法:

class ImageData:    

    def generate_voronoi_diagram(self, seeds):
    """
    Generate a voronoi diagram with *seeds* seeds
    :param seeds: the number of seed in the voronoi diagram
    """
    nx = []
    ny = []
    gs = []
    for i in range(seeds):
        # Generate a cell position
        pos_x = random.randrange(self.width)
        pos_y = random.randrange(self.height)
        nx.append(pos_x)
        ny.append(pos_y)

        # Save the f(x,y) data
        x = Utils.translate(pos_x, 0, self.width, self.range_min, self.range_max)
        y = Utils.translate(pos_y, 0, self.height, self.range_min, self.range_max)
        z = Utils.function(x, y)

        gs.append(z)

    for y in range(self.height):
        for x in range(self.width):
            # Return the Euclidean norm
            d_min = math.hypot(self.width - 1, self.height - 1)
            j = -1
            for i in range(seeds):
                # The distance from a cell to x, y point being considered
                d = math.hypot(nx[i] - x, ny[i] - y)
                if d < d_min:
                    d_min = d
                    j = i
            self.data[x][y] = gs[j]

我必须生成大量的这个图表,因此,这会耗费大量时间,所以我认为这是一个典型的并行化问题。 我是这样做的,采用“正常”方法,如下:

if __name__ == "__main__":
    entries = []
    for n in range(images):
        entry = ImD.ImageData(width, height)
        entry.generate_voronoi_diagram(seeds)
        entry.generate_heat_map_image("ImagesOutput/Entries/Entry"+str(n))
        entries.append(entry)

尝试并行化这个,我尝试了这个:

if __name__ == "__main__":
    entries = []
    seeds = np.random.poisson(100)
    p = Pool()
    entry = ImD.ImageData(width, height)
    res = p.apply_async(entry.generate_voronoi_diagram,(seeds))
    entries.append(entry)
    entry.generate_heat_map_image("ImagesOutput/Entries/EntryX")

但是,除了它甚至不能生成单个图表,我不知道如何指定必须进行N次。

非常感谢任何帮助。 感谢。

2 个答案:

答案 0 :(得分:1)

Python的多处理不共享内存(除非你明确告诉它)。这意味着您不会看到在工作进程中运行的任何函数的“副作用”。您的generate_voronoi_diagram方法的工作原理是将数据添加到entry值,这是一个副作用。为了查看结果,您需要将其作为函数的返回值传回。

这是一种将entry实例作为参数处理并返回值的方法:

def do_voroni(entry, seeds):
    entry.generate_voronoi_diagram(seeds)
    return entry

现在,您可以在工作进程中使用此功能:

if __name__ == "__main__":
    entries = [ImD.ImageData(width, height) for _ in range(images)]
    seeds = numpy.random.poisson(100, images) # array of values

    pool = multiprocessing.Pool()
    for i, e in enumerate(pool.starmap_async(do_voroni, zip(entries, seeds))):
        e.generate_heat_map_image("ImagesOutput/Entries/Entry{:02d}".format(i))

循环中的e值不是对entries列表中值的引用。相反,它们是这些对象的副本,这些对象已传递给工作进程(向其添加数据)然后传回。

答案 1 :(得分:0)

我可能错了,但我认为你应该使用

res = p.apply_async(entry.generate_voronoi_diagram,(种子))

res.get(超时= 1)

你可能会得到不能腌制类型'instancemethod'

我认为最简单的方法就像

import random
from multiprocessing import Pool


class ImageData:

    def generate_voronoi_diagram(self, seeds):
        ooxx

    def generate_heat_map_image(self, path):
        ooxx

def allinone(obj, seeds, path):
    obj.generate_voronoi_diagram(seeds)
    obj.generate_heat_map_image(path)

if __name__ == "__main__":
    entries = []
    seeds = random.random()
    p = Pool()
    entry = ImageData()
    res = p.apply_async(allinone, (entry, seeds, 'tmp.txt'))
    res.get(timeout=1)