0

我再次有一个关于大循环的问题。

假设我有一个功能

limits

def limits(a,b):
  *evaluate integral with upper and lower limits a and b*
  return float result

A 和 B 是存储我的值 a 和 b 的简单 np.arrays。现在我想计算积分 300'000^2/2 次,因为 A 和 B 的长度分别为 300'000 并且积分是对称的。

在 Python 中,我尝试了几种方法,例如itertools.combinations_with_replacement创建 A 和 B 的组合,然后将它们放入积分中,但这需要大量时间并且内存完全过载。有什么方法可以加快速度,例如用另一种语言传输循环?

我想运行循环

for i in range(len(A)):
  for j in range(len(B)):
    np.histogram(limits(A[i],B[j]))

我认为对返回进行直方图limits是可取的,以免存储成正比增长的额外数组。

从我读到的内容来看,python 并不是这种迭代分析的最佳选择。

那么在 Python 中用另一种语言评估这个循环是否合理,如果是,如何做。我知道有一些方法可以传输代码,但到目前为止我还没有这样做过。

谢谢你的帮助。

4

1 回答 1

0

如果您担心内存占用,您需要做的就是在 for 循环中对结果进行分类。

num_bins = 100
bin_upper_limits = np.linspace(-456, 456, num=num_bins-1)
# (last bin has no upper limit, it goes from 456 to infinity)
bin_count = np.zeros(num_bins)
for a in A:
    for b in B:
        if b<a:
             # you said the integral is symmetric, so we can skip these, right?
             continue
        new_result = limits(a,b)
        which_bin = np.digitize([new_result], bin_upper_limits)
        bin_count[which_bin] += 1

所以没有什么大的东西保存在内存中。

至于速度,我想绝大多数时间都花在了评估limits(a,b)上。在这种情况下,循环和分箱非常快,即使在 python 中也是如此。要说服自己相信这一点,请尝试将行替换new_result = limits(a,b)new_result = 234. 你会发现循环运行得非常快。(在我的电脑上几分钟,比你引用的 4 小时数字要少得多。)与 C 相比,Python 的循环速度并不快,但在这种情况下并不重要。

无论你做什么来加速limits()调用(包括用另一种语言实现它)都会加速程序。

如果你改变算法,还有很大的改进空间。让我们举一个例子来说明你在做什么。假设 A 和 B 是 0,1,2,3。您正在集成 0-->0、0-->1、1-->1、1-->2、0-->2 等范围内的函数。您正在重新执行一遍又一遍地做同样的工作。如果你已经积分了 0-->1 和 1-->2,那么你可以将这两个结果相加得到积分 0-->2。您不必使用花哨的积分算法,只需添加两个您已经知道的数字。

因此,在我看来,您可以计算所有最小范围(0-->1、1-->2、2-->3)中的积分,将结果存储在数组中,并添加结果的子集以获得在你想要的任何范围内的积分。如果您希望该程序在几分钟内而不是 4 小时内运行,我建议您按照这些思路考虑一种替代算法。

(抱歉,如果我误解了您要解决的问题。)

于 2013-01-04T16:19:35.070 回答