带有多个参数的Python multiprocessing pool.map
我需要一些帮助,因为我已经试了两天了,我不知道怎么才能做到。我有一个函数带有多个参数的Python multiprocessing pool.map,python,parallel-processing,multiprocessing,Python,Parallel Processing,Multiprocessing,我需要一些帮助,因为我已经试了两天了,我不知道怎么才能做到。我有一个函数compute_desc,它接受多个参数(准确地说是5个),我想并行运行这个函数。 我现在有这个: def compute_desc(coord, radius, coords, feat, verbose): # Compute here my descriptors return my_desc # numpy array (1x10 dimensions) def main(): points
compute_desc
,它接受多个参数(准确地说是5个),我想并行运行这个函数。
我现在有这个:
def compute_desc(coord, radius, coords, feat, verbose):
# Compute here my descriptors
return my_desc # numpy array (1x10 dimensions)
def main():
points = np.rand.random((1000000, 4))
coords = points[:, 0:3]
feat = points[:, 3]
all_features = np.empty((1000000, 10))
all_features[:] = np.NAN
scales = [0.5, 1, 2]
for radius in scales:
for index, coord in enumerate(coords):
all_features[index, :] = compute_desc(coord,
radius,
coords,
feat,
False)
我想将其并行化。我看到了几个使用池的解决方案,但我不明白它是如何工作的
我尝试使用pool.map()
,但只能向函数发送一个参数
这是我的解决方案(它不起作用):
但我怀疑它能否与numpy阵列配合使用
编辑
这是我使用池的最低代码(现在可以使用):
通用解决方案是将一系列元组传递给
Pool.map
,每个元组包含一组辅助函数的参数,然后在辅助函数中解压该元组
因此,只需将函数更改为只接受一个参数,即参数的元组,您已经用zip
准备好并传递到Pool.map
。然后只需将args
解包为变量:
def compute_desc(args):
coord, radius, coords, feat, verbose = args
# Compute here my descriptors
另外,Pool.map
也应该与numpy
类型一起工作,因为它们毕竟是有效的Python类型
只要确保正确地zip
5个序列,您的函数就会收到一个5元组。您不需要在coords
中迭代点
,zip
将为您完成以下操作:
args = zip(coords, repeat(radius), repeat(coords), repeat(feat), repeat(False))
# args is a list of [(coords[0], radius, coords, feat, False), (coords[1], ... )]
(如果您这样做,并将点
作为zip
的第一个序列,则zip
将在该点上迭代,在本例中为3元素数组)
您的Pool.map
行应该如下所示:
for radius in scales:
args = zip(coords, repeat(radius), repeat(coords), repeat(feat), repeat(False))
feat_one_scale = [pool.map(compute_desc_pool, args)]
# other stuff
对于您的情况,除了一个参数是固定的以外,所有参数都是固定的,特定的解决方案可以是使用
functools.partial
(如另一个答案所示)。此外,您甚至不需要在第一个参数中解包coords
,只需在coords
中传递索引[0..n]
,因为每次调用worker函数都会收到完整的coords
数组。从您的示例中,我假设这五个参数中的四个对于计算描述池的所有调用都是常量。如果是,则可以使用partial
执行此操作
from functools import partial
....
def compute_desc_pool(coord, radius, coords, feat, verbose):
compute_desc(coord, radius, coords, feat, verbose)
def main():
points = np.random.rand(1000000, 4)
coords = points[:, 0:3]
feat = points[:, 3]
feat_one_scale = np.empty((1000000, 10))
feat_one_scale[:] = np.NAN
scales = [0.5, 1, 2]
pool = Pool()
for radius in scales:
feat_one_scale = [pool.map(partial(compute_desc_pool, radius, coords,
feat, False), coords)]
不,它不起作用,我用一个中间函数尝试了你的解决方案(我想保留我的原始函数),但我有以下错误:ValueError:太多的值无法解包(预期为6)
。请用准确的代码更新你的问题,这样错误就可以重现。并且请写下它,以便任何人都可以复制/粘贴它并尝试它(不丢失导入等)。看,好极了!所以问题出在您的zip
表达式中。检查我的更新。它现在可以工作了!但是我有点惊讶,我在一个有56个进程的服务器上运行这个脚本,我不希望我的代码运行快56倍,但至少要快3倍,而且添加Pool(),我增加了计算时间,而在您的示例中我没有太多的要点(例如大约1000个),为什么要定义compute\u desc\u Pool
,当它采用与compute_desc
相同的参数时,因为这是原始问题的结构。当然可以简化。问题显然是关于在使用Pool.map()
时将静态参数与映射参数一起传递,而不是对仅作为示例提供的代码进行简单简化。
for radius in scales:
args = zip(coords, repeat(radius), repeat(coords), repeat(feat), repeat(False))
feat_one_scale = [pool.map(compute_desc_pool, args)]
# other stuff
from functools import partial
....
def compute_desc_pool(coord, radius, coords, feat, verbose):
compute_desc(coord, radius, coords, feat, verbose)
def main():
points = np.random.rand(1000000, 4)
coords = points[:, 0:3]
feat = points[:, 3]
feat_one_scale = np.empty((1000000, 10))
feat_one_scale[:] = np.NAN
scales = [0.5, 1, 2]
pool = Pool()
for radius in scales:
feat_one_scale = [pool.map(partial(compute_desc_pool, radius, coords,
feat, False), coords)]