python process参数,如何将具有多个参数的函数传递给python concurrent.futures.ProcessPoolExecutor.map()?...

我希望concurrent.futures.ProcessPoolExecutor.map()调用一个由2个或更多参数组成的函数。在下面的示例中,我使用lambda函数并将ref定义为具有相同值的numberlist的大小相等的数组。

第一个问题:有更好的方法吗?在numberlist的大小可能是数百万到数十亿个元素的情况下,因此ref大小必须遵循numberlist,这种方法不必要地占用宝贵的内存,我想避免。我这样做是因为我读到map函数将终止其映射,直到达到最短的数组结束。

import concurrent.futures as cf

nmax = 10

numberlist = range(nmax)

ref = [5, 5, 5, 5, 5, 5, 5, 5, 5, 5]

workers = 3

def _findmatch(listnumber, ref):

print('def _findmatch(listnumber, ref):')

x=''

listnumber=str(listnumber)

ref = str(ref)

print('listnumber = {0} and ref = {1}'.format(listnumber, ref))

if ref in listnumber:

x = listnumber

print('x = {0}'.format(x))

return x

a = map(lambda x, y: _findmatch(x, y), numberlist, ref)

for n in a:

print(n)

if str(ref[0]) in n:

print('match')

with cf.ProcessPoolExecutor(max_workers=workers) as executor:

#for n in executor.map(_findmatch, numberlist):

for n in executor.map(lambda x, y: _findmatch(x, ref), numberlist, ref):

print(type(n))

print(n)

if str(ref[0]) in n:

print('match')

运行上面的代码,我发现map函数能够实现我想要的结果。但是,当我将相同的术语转移到concurrent.futures.ProcessPoolExecutor.map()时,python3.5失败并出现此错误:

Traceback (most recent call last):

File"/usr/lib/python3.5/multiprocessing/queues.py", line 241, in _feed

obj = ForkingPickler.dumps(obj)

File"/usr/lib/python3.5/multiprocessing/reduction.py", line 50, in dumps

cls(buf, protocol).dump(obj)

_pickle.PicklingError: Can't pickle at 0x7fd2a14db0d0>: attribute lookup on __main__ failed

问题2:为什么会出现此错误?如何使用concurrent.futures.ProcessPoolExecutor.map()调用具有多个参数的函数?

要先回答你的第二个问题,你会得到一个例外,因为像你正在使用的lambda函数是不可选择的。由于Python使用pickle协议来序列化主进程和ProcessPoolExecutor的工作进程之间传递的数据,因此这是一个问题。目前尚不清楚为什么要使用lambda。你拥有的lambda有两个参数,就像原始函数一样。您可以直接使用_findmatch而不是lambda,它应该可以工作。

with cf.ProcessPoolExecutor(max_workers=workers) as executor:

for n in executor.map(_findmatch, numberlist, ref):

...

关于传递第二个常量参数而不创建巨型列表的第一个问题,您可以通过多种方式解决这个问题。一种方法可能是使用itertools.repeat创建一个可迭代的对象,在迭代时永远重复相同的值。

但是更好的方法可能是编写一个额外的函数来为你传递常量参数。 (也许这就是你尝试使用lambda函数的原因?)如果您使用的函数可以在模块的顶级命名空间访问,它应该可以工作:

def _helper(x):

return _findmatch(x, 5)

with cf.ProcessPoolExecutor(max_workers=workers) as executor:

for n in executor.map(_helper, numberlist):

...

你是对的,我使用了试验lambda,因为当ref是一个常数时,我最初遇到了将带有2个参数的函数传递到executor的问题。将ref转换为大小等于numberlist的列表后,我才意识到我忘了删除lambda。我真正想要的是ref是常数或类似的解决方案。所以辅助功能& itertools.repeat你提到过工作。谢谢。

我想邀请您回答我的后续问题,其中我用Executor.map对Executor.map的性能进行基准测试,发现前者明显变慢了,我想知道为什么?

(1)无需列出清单。您可以使用itertools.repeat创建一个只重复某个值的迭代器。

(2)您需要将命名函数传递给map,因为它将传递给子进程执行。 map使用pickle协议发送内容,lambdas无法腌制,因此它们不能成为地图的一部分。但它完全没必要。你所做的所有lambda都是用2参数调用2参数函数。完全删除它。

工作代码是

import concurrent.futures as cf

import itertools

nmax = 10

numberlist = range(nmax)

workers = 3

def _findmatch(listnumber, ref):

print('def _findmatch(listnumber, ref):')

x=''

listnumber=str(listnumber)

ref = str(ref)

print('listnumber = {0} and ref = {1}'.format(listnumber, ref))

if ref in listnumber:

x = listnumber

print('x = {0}'.format(x))

return x

with cf.ProcessPoolExecutor(max_workers=workers) as executor:

#for n in executor.map(_findmatch, numberlist):

for n in executor.map(_findmatch, numberlist, itertools.repeat(5)):

print(type(n))

print(n)

#if str(ref[0]) in n:

#    print('match')

感谢您的解释和解决方案。 :)

我想邀请您回答我的后续问题,其中我用Executor.map对Executor.map的性能进行基准测试,发现前者明显变慢了,我想知道为什么?

关于你的第一个问题,我是否正确理解你想要传递一个参数,该参数的值仅在你调用map时确定,但对于映射函数的所有实例都是常量?如果是这样,我将使用从"模板函数"派生的函数执行map,并使用functools.partial将第二个参数(在您的示例中为ref)烘焙到其中:

from functools import partial

refval = 5

def _findmatch(ref, listnumber):  # arguments swapped

...

with cf.ProcessPoolExecutor(max_workers=workers) as executor:

for n in executor.map(partial(_findmatch, refval), numberlist):

...

回覆。问题2,第一部分:我还没有找到试图挑选(序列化)应该并行执行的函数的确切代码片段,但这听起来很自然 - 不仅是参数而且还有该功能必须以某种方式转移给工人,并且可能必须为此转移进行序列化。事实上partial的功能可以被腌制,而lambda s则无法在其他地方提到,例如:https://stackoverflow.com/a/19279016/6356764。

回覆。问题2,第二部分:如果你想在ProcessPoolExecutor.map中调用一个带有多个参数的函数,你可以将函数作为第一个参数传递给它,然后是函数的第一个参数的可迭代函数,接着是一个可迭代的它的第二个论点等。在你的情况下:

for n in executor.map(_findmatch, numberlist, ref):

...

感谢分享。 :)你的解决方案有效。这是我第一次学习偏爱。

我想邀请您回答我的后续问题,其中我用Executor.map对Executor.map的性能进行基准测试,发现前者明显变慢了,我想知道为什么?

@mkorvas我用你的问题解决了我的问题stackoverflow.com/questions/56492876/…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值