【问题标题】:Python: Memory optimised way of defining matrices in numpyPython:在 numpy 中定义矩阵的内存优化方式
【发布时间】:2013-07-06 00:59:05
【问题描述】:
import numpy as np

前言:

如果您已经知道这一点,如果您觉得无聊,请跳过前言。

我最近在调试时遇到了一个问题。我写了 `A = B = C = np.zeros([3,3]) 我以为我刚刚定义了三个新矩阵。我所做的实际上是不同的。我定义了一个新矩阵(用零填充)和三个标签,每个标签都指向同一个矩阵。让我用下面的例子来说明:

>>> a = b = [0,0]
>>> a
[0,0]
>>> b
[0,0]
>>> # All good so far.
>>> a[0] = 1
>>> a
[1,0]
>>> # Nothing short of what one would expect...
>>> b
[1,0]
>>> # ... but since 'b' is assigned tot he same tuple, it changes as well.

问题:

嗯。现在我知道这没问题了,对吧?当然我可以写:

A = np.zeros([3,3])
B = np.zeros([3,3])
C = np.zeros([3,3])

一切正常吗?没错,但我同样可以写:

A, B, C = np.zeros([3,3,3])

我认为第二个选项以更有效的方式使用内存,因为它定义了一个 3x3x3 张量,然后为每个层定义了 3 个标签 A、B 和 C,而不是三个单独的矩阵,它们之间可能存在内存位。

你觉得哪个更好?

【问题讨论】:

  • 不幸的是,这可能会被关闭,因为它不是 SO 的正确格式。 .. 但只需运行 timeit 并查看您的 procmon 以查看两者的内存和时间足迹......人们认为完全无关紧要,您自己检查指标很容易
  • 如果您希望将 3D 数组用于某事(例如计算所有 3 个矩阵的元素平均值),通常只进行解包操作,这当然需要给它一个标签:@ 987654325@。这主要是个人喜好问题,尽管如果您的阵列非常大,那么找到三个三分之一大小的插槽可能比一个完整大小的插槽更容易。

标签: python memory memory-management numpy matrix


【解决方案1】:

最重要的是,它闻起来像是过早的优化。如果我们谈论的是少数矩阵,那两种方式都没有关系。如果我们谈论的是大量矩阵,您不太可能使用解包。

话虽如此,第二个选项涉及创建更大的底层存储,而第一个选项创建三个独立的存储。如果所有三个矩阵共享相同的生命周期,前者的效率会更高一些。后者更具可读性,并允许释放单个矩阵的内存。如果这种优化对您来说很重要,请衡量。

【讨论】:

  • 我不确定您是否非常了解 numpy 如何处理内存和视图...您所说的“垃圾”是什么意思?像解包这样的标准功能如何损害可读性?您如何认为前一种方法会更节省内存?
  • @Jaime 你说得对,我说得太早了,指的是“垃圾”。我现在更新了答案,以更准确地反映所涉及的权衡。
【解决方案2】:

我做了一个简单的测试,看看这两种情况发生了什么(代码和结果如下)。正如怀疑的那样,后一种方法线性分配内存,而前者将它分散在系统允许的任何地方(我本以为它会比以前更紧密)。 所以后者在内存位置方面效率更高。但就分配时间(为下面的脚本计时)而言,它们是等价的(解包似乎占用了一些时间,而且我们谈论的数字几乎很小)。因此,考虑这一点很可能是过早的优化。

import sys
import numpy as np
nr = 1000
rounds =1000
if len(sys.argv)==2:
    if sys.argv[1]=='seq':
        print "testing sequential allocation"
        for i in xrange(rounds):
            a=np.zeros([nr,nr])
            b=np.zeros([nr,nr])
            c=np.zeros([nr,nr])
    elif sys.argv[1]=='all':
        print "testing allocating all at once"
        for i in xrange(rounds):
            A,B,C=np.zeros([3,nr,nr])
        
        
a=np.zeros([3,3])
b=np.zeros([3,3])
c=np.zeros([3,3])
A,B,C=np.zeros([3,3,3])

print "diff in location b-a", b.__array_interface__['data'][0]-a.__array_interface__['data'][0]
print "diff in location c-a", c.__array_interface__['data'][0]-a.__array_interface__['data'][0]
print "diff in location B-A", B.__array_interface__['data'][0]-A.__array_interface__['data'][0]
print "diff in location C-A", C.__array_interface__['data'][0]-A.__array_interface__['data'][0]

输出

> 位置 b-a -125520 的差异

>位置 c-a -173376 的差异

>位置 B-A 72 的差异

>位置 C-A 144 的差异

【讨论】:

    猜你喜欢
    • 2014-01-13
    • 2015-10-02
    • 1970-01-01
    • 1970-01-01
    • 2020-03-23
    • 1970-01-01
    • 1970-01-01
    • 2022-08-13
    • 2017-06-28
    相关资源
    最近更新 更多