我正在尝试学习如何在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次。
非常感谢任何帮助。 感谢。
答案 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)