我应该预分配一个numpy数组吗?

7
我有一个类和它的方法。在执行期间,该方法会重复多次。该方法使用一个numpy数组作为临时缓冲区。我不需要在方法调用之间存储缓冲区内的值。我应该创建一个成员实例数组来避免在方法执行期间出现时间泄漏吗?我知道最好使用局部变量。但是Python是否足够聪明,只分配一次数组的内存?
class MyClass:
    def __init__(self, n):
        self.temp = numpy.zeros(n)
    def method(self):
        # do some stuff using self.temp

或者

class MyClass:
    def __init__(self, n):
        self.n = n
    def method(self):
        temp = numpy.zeros(self.n)
        # do some stuff using temp

更新:将np.empty替换为np.zeros


2
np.empty 是一种惰性分配器。我的猜测是你需要尝试两种方式,看看在样本操作中是否有时间差异。 - hpaulj
当我在不同的地方使用预分配或本地定义时,我看到平均时间同时增加和减少。因此,我无法区分哪种方法更好。 - Leonid
1
我并不感到惊讶。有时它会向操作系统请求更多的内存,而有时它会重复使用垃圾收集的空间。 - hpaulj
2个回答

3

Numpy数组一旦创建就非常快。然而,创建一个数组的代价相当昂贵,比如说比创建一个Python列表要昂贵得多。

在您的情况下,如果您需要在循环中反复创建新数组,我建议您始终预先分配数组结构并重复使用它。

我无法评论Python是否足够聪明以优化此问题,但我猜测它不会 :)

您的数组有多大,调用此方法的频率如何?


该数组包含大约1000个浮点元素。调用并不是非常频繁,但如果发生调用,应尽可能快地执行。 - Leonid
1
这并不多。但是 - 在__init__内准备好你的数组并让它准备就绪。此外,正确设置其类型可能是一个好主意,例如:self.temp = numpy.zeros(n, dtype='float64') - matjazzz144

1
是的,您需要预先分配大数组。但是,这是否有效取决于您如何使用这些数组。

这将导致计算的中间结果进行多次新的分配:

self.temp = a * b + c

这不会发生(如果self.x是预分配的):

numpy.multiply(a, b, out=self.x)
numpy.add(c, self.x, out=self.temp)

但对于这些情况(当您在不平凡的公式中使用大型数组时),最好使用numexpreinsum进行矩阵计算。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接