【问题标题】:Evaluating a function parallely using itertools product使用 itertools 产品并行评估函数
【发布时间】:2016-07-03 21:16:58
【问题描述】:

我必须评估一个函数(我们称之为 my_func()),它接受 8 个参数作为输入,并在不同的矩阵计算中返回一个标量。由于我对 my_func() 没有任何约束,我别无选择,只能强行强制所有等于 8^8 = 16777216 的可能性。我开始使用 itertools 的产品函数并将生成的序列依次传递给 my_func() .请看下面我的代码示例,

到目前为止.....

from itertools import product
import numpy as np

def my_func(a,b,c,d,e,f,g,h): #Function that I have to evaluate
    #do some matrix computations and return some scalar q# 
    return q

def Evaluate():
    Range = [x for x in np.arange(0,3.60,0.5)] # A list that contains 8 elements
    it = itertools.product(Range, repeat=8) #Generate all possiblities
    Max = 0
    for i in it:
        Sum = my_func(*i)
        if Sum > Max:
            Max = present
    return Max

Result = Evaluate() #Output

陷阱...

不幸的是,按顺序执行上述代码需要很长时间才能产生输出。这是因为 my_func 非常重。我别无选择,只能以某种方式并行化这段代码,以便我可以利用多个处理器来运行我的代码。

问题:

由于 itertools.product 是一个生成器,我无法将其并行化以同时针对不同的参数集评估 my_func()。 有什么办法可以并行化代码吗?如果不是,我应该放弃使用 itertools 的想法并尝试其他方法吗?

请帮我找到解决办法。

感谢您提出任何想法。

干杯!!

【问题讨论】:

  • 是在索引排列下返回标量对称的函数吗?如果我执行 f(1,0,0...,0) 是否返回与 f(0,0,...,1) 相同的结果?
  • 不幸的是,标量在排列下不是对称的,我希望它本来就是这样。该函数为不同的参数集返回不同的值。
  • 您的代码似乎缺少一行,例如for i in it:。顺便说一句,my_func(*i) 比您的电话更紧凑。也可以考虑Range = [i/2 for i in range(8)];如果您在 Python 2 上而不使用 from __future__ import division,请使用 i/2.
  • @PM 2Ring 感谢您的建议。我已将缺少的行添加到我的代码中。干杯!!

标签: python multiprocessing


【解决方案1】:

您可以并行化生成器!您可以使用 multiprocessing 库,它提供了 Pool 类,它完全符合您的要求。 Here 你可以获得更多的文档,但本质上,你想要做的是:

with Pool(processes=4) as pool:
  pool.map(my_func, itertools.product(Range, repeat=8))

您应该查看pool.map 的替代品,以找到最适合您的。

【讨论】:

  • 感谢您的快速回复。我注意到通过将 itertools.product(Range, repeat=8) 映射到 my_func,很快就会耗尽内存。我认为所有 8^8 的可能性都是生成、存储的,然后作为块传递给不同的处理器。有什么解决方法吗?
  • 您可能想查看此处给出的答案:stackoverflow.com/questions/5318936/… 和此处:stackoverflow.com/questions/14677287/…
【解决方案2】:

您将使用的内核数量可能比 88 少得多。

这导致了以下并行化方案。拨打multiprocessing.Pool.map

itertools.product(<all-combinations-of-first-2-or-3-parameters>)

在每个进程中,对剩余参数执行并行化,并仅返回一个结果 - 找到的最佳参数元组。

这将比传递每个 88 组合更有效。这些东西都有开销。

示例

假设您决定映射前三个参数。那么你的product 是一个三元组序列:..., (1, 3, 2), ...。你在每个这样的三元组上都使用multiprocessing.Pool.map 之类的东西,所以让我们从函数的角度来考虑:

def find_best_for_triplet(xyz):
    x, y, z = xyz[0], xyz[1], xyz[2]

    for ... in itertools.product(<all-combinations-of-last-5-parameters>)
        # Here you have all 8 of your parameters: x, y, z, and the last 5

    return xyz + (last-five-parameters) of the min

另外一个问题——在实践中,Nelder Mead method 在优化高维问题方面效果很好,而且比蛮力便宜得多。您可能希望尝试一下它的实现。

【讨论】:

  • 您好 Tavory 博士,感谢您的帮助。当然传递 8^8 组合是很多开销,实际上参数的数量甚至会上升到 10,然后我不得不蛮力 10^10 这太可怕了。我多次阅读您的答案,但无法理解它。您是否建议在单个进程中仅使用参数子集(保留其余 const)来评估函数?您能否在回答中进一步解释一下?
  • @Prdeep_nitro 我添加了一个澄清/解释。如果您需要进一步的信息,请告诉我。
猜你喜欢
  • 1970-01-01
  • 2018-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多