【问题标题】:Static memory in python: do loops create new instances of variables in memory?python中的静态内存:循环会在内存中创建新的变量实例吗?
【发布时间】:2010-07-22 04:56:29
【问题描述】:

我一直在运行 Python 脚本,这些脚本多次调用某些函数,例如 F1(x) 和 F2(x),看起来有点像这样:

x = LoadData()

for j in range(N):
    y = F1(x[j])
    z[j] = F2(y)

    del y

SaveData(z)

如果我保留“del y”行,性能会快很多。但我不明白为什么这是真的。如果我不使用“del y”,那么我很快就会用完 RAM,不得不求助于虚拟内存,一切都会慢下来。如果我使用“del y”,则购买,然后我会反复刷新并为 y 重新分配内存。我想做的是让 y 作为静态内存,并在每次 F1(x) 调用时重用内存。但据我所知,事实并非如此。

另外,不确定它是否相关,但我的数据由 numpy 数组组成。

【问题讨论】:

  • 这个问题可能假设 y 首先在循环内声明,我应该提到这一点。不过,请随意评论问题的这方面!
  • 如果你不喜欢显式的del y,那么将循环体提取到一个函数中。这样,任何完全在循环内的变量都将在每次迭代时自动清理。
  • @Duncan 我做了同样的事情,但它仍然具有相同的行为。我做错了什么还是正常行为?

标签: python memory


【解决方案1】:

如果没有del y,您可能需要两倍的内存。这是因为对于每次循环,y 绑定到 F1 的前一个值,同时计算下一个值。

一旦F1 返回 y 就会反弹到该新值,并且可以释放旧的 F1 结果。

这意味着F1返回的对象占用了相当多的内存

在前几次迭代中展开循环看起来像这样

y = F1(x[0])   # F1(x[0]) is calculated, then y is bound to it
z[j] = F2(y)
y = F1(x[1])   # y is still bound to F1(x[0]) while F1(x[1]) is computed
               # The memory for F1(X[0]) is finally freed when y is rebound
z[j] = F2(y)

如果您遇到这种情况,使用 del y 是一个很好的解决方案。

【讨论】:

  • 听听听听 -- 这完全解释了为什么使用del y 会有更好的性能
  • 谢谢,这一定是正在发生的事情:如果没有 del,我的内存使用量会翻倍,会溢出一点到虚拟内存中(因为我的 RAM 恰好位于 y 的一到两个实例之间)并且脚本以低性能运行。我现在会坚持使用 del 解决方案;再次感谢您解释何时/如何创建 y 的实例。
【解决方案2】:

你真正想要的是在python中做的很奇怪的事情——你想为y分配一个内存区域并将指向该区域的指针传递给F1(),以便它可以使用该区域来构建y 的下一个值。这避免了F1() 自己分配y 的新值,然后将其引用写入您自己的变量y(这实际上不是F1() 计算的任何值,而是对它)

已经有一个关于在 python 中通过引用传递的 SO 问题:How do I pass a variable by reference?

【讨论】:

    【解决方案3】:

    对于非常大的 N 值,请使用 xrange 而不是 range 以节省内存。你也可以嵌套函数,但我不知道这是否对你有帮助。 :\

    x = LoadData()
    
    for j in xrange(N):
        z[j] = F2(F1(x[j]))
    
    SaveData(z)
    

    也许 F1 和 F2 正在制作不必要的对象副本,最好的方法是就地复制,例如:

    x = LoadData()
    for item in x:
        item.F1()
        item.F2()
    SaveData(x)
    

    对不起,如果可能回答没有帮助

    【讨论】:

    • 我担心我的例子会允许嵌套;在实际脚本中,它不是一个实用的选项。我认为 gnibbler 的反馈正确地描述了这种情况,但感谢您的反馈。在您指出之前,我对 xrange 函数并不熟悉。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-22
    • 2017-01-24
    • 2021-01-20
    • 2015-06-25
    • 1970-01-01
    • 1970-01-01
    • 2011-01-26
    相关资源
    最近更新 更多