【问题标题】:Optimizing nested Python for loops?优化嵌套 Python for 循环?
【发布时间】:2017-05-28 05:52:05
【问题描述】:

我在优化以下 for 循环时遇到了一些麻烦。我研究了 map 函数、理解表达式以及一些 itertools 和生成器,但不确定如何优化嵌套循环。非常感谢任何帮助或建议。提前致谢!

注意对象架构是:

self.variables.parameters.index1/index2/value
self.variables.rate
self.state.num

循环 1:

mat1 = np.zeros(m, n)
for idx, variable in enumerate(self.variables):
    for parameter in variable.parameters:
        tracking_idx = parameter.index1 + parameter.index2
        mat1[tracking_idx, idx] = parameter.value

循环 2:

mat2 = []
for variable in self.variables:
    rate = variable.rate
    for parameter in variable.parameters:
        if parameter.value < 0 and self.state.num[parameter.index1, parameter.index2] <= 0:
            rate = 0
    mat2.append(rate)

【问题讨论】:

  • 对于第二个循环,如果您有大量参数,在 rate = 0 语句后添加一个中断可能会有所帮助,因为它会停止检查其他参数

标签: python numpy for-loop optimization nested


【解决方案1】:

使用numpy 标签,我假设“优化”意味着将这些循环转换为已编译的 numpy 数组表达式。我认为没有办法不首先将所有数据收集为 numpy 数组,这将需要相同的循环。

您有一个nvariables 的列表。每个变量都有一个? 参数列表。每个参数有 3 或 4 个属性。

所以

rates = np.array([v.rate for v in variables])
values = np.array([[p.value for p in v.parameters] for v in variables]
index1s = <dito>   (?,n) array
index2s = <dita>   (?,n) array

self.state.num 已经是一个二维数组,大小与index1sindex2s 中的值范围兼容。

鉴于这些一维数组和二维数组,我们应该能够通过整个数组操作导出mat1mat2。如果? 相对于mindex1index2 中的值范围较小,则可能值得这样做。我对你的数据没有真实的感觉。

============

你提到了the map function, comprehension expressions, and a bit of itertools and generators。这些可以使代码看起来更干净一些,但对速度没有太大影响。

我演示了列表推导的使用。这些表达可以更精细,但通常以可读性为代价。我喜欢编写辅助函数来隐藏细节。生成器推导可以替换提供另一个推导的列表推导。地图涵盖相同的功能。

由于variablesparameters 具有属性,我假设您已经在类中定义了它们。您可以编写将这些属性提取为简单列表或数组的方法。

class Variable(....):
   ....
   def get_values(self):
       return [p.value for p in self.parameters]
   def get_rate(self, state):
       rate = self.rate
       for parameter in self.parameters:
            if parameter.value < 0 and                
                state.num[parameter.index1, parameter.index2] <= 0:
            rate = 0
       return rate

values = [v.get_values() for v in variables]
rates = [v.get_rate(self.state) for v in variables]

您甚至可以在没有类结构的情况下编写这些辅助函数。

这不会加速任何事情;它只是隐藏了对象中的一些细节。

【讨论】:

  • 谢谢!我对 mat1 使用了列表推导,并为 mat2 保留了 for 循环。它减少了 20% 左右的运行时间!
猜你喜欢
  • 2012-01-27
  • 2020-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-23
相关资源
最近更新 更多