带有多个参数的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)]