【问题标题】:Avoid repetitive big arrays computation inside a function in Python避免在 Python 中的函数内进行重复的大数组计算
【发布时间】:2019-05-01 07:38:35
【问题描述】:

我在最小化过程中反复调用一个需要大数组的函数。这是一个虚拟示例

def foo(N,a):
    big_array = np.mgrid[0:N,0:N]
    b = np.fft.fft2(big_array[0]**a) #some heavy computation
    return b

在最小化过程中,数组大小N不会改变,所以我想使用相同的数组来避免无用的计算和内存分配。

我还希望函数 foo 是自洽的,这意味着我不希望另一个函数在最小化过程中创建数组并将其提供给 foo

鉴于这些要求,我正在考虑使用带有数组作为属性的可调用对象。你怎么看待这件事?有没有更pythonic的方法?

【问题讨论】:

  • 您的意思是要避免分配或计算?
  • 我想避免big_array = np.mgrid[0:N,0:N]这一行的无用重复。目标是让程序更快

标签: python arrays numpy memory optimization


【解决方案1】:

一个自包含的方法(没有全局变量)是使用一个可变的默认参数(你不应该用它来调用你的函数)来记忆以前分配的数组给定它们的大小

如果数组大小不在字典中,则创建并添加它。

def foo(N,a,dict_container={}):
    if N in dict_container:
        big_array = dict_container[N]
    else:
        big_array = np.mgrid[0:N,0:N]
        dict_container[N] = big_array

    b = np.fft.fft2(big_array[0]**a) #some heavy computation
    return b

这种方法的主要问题是它禁用了这个数组的垃圾收集器,所以如果N 变化太大,你可能会出现内存耗尽。相同的技术,但使用LRU cache 可以解决问题:

from functools import lru_cache
@lru_cache(maxsize=32)  # max 32 elements in cache
def get_matrix(N):
    return np.mgrid[0:N,0:N]

def foo(N,a):
    big_array = get_matrix(N)
    b = np.fft.fft2(big_array[0]**a) #some heavy computation
    return b

(不要在foo 中定义get_matrix,否则每次调用都会重新初始化缓存)

【讨论】:

  • 如果N 不是整数而是 numpy 数组会怎样?事实上,我的 get_matrix 函数可能会将一个数组作为输入并返回另一个数组......以前的方法都返回一个 unhashable type 错误
  • 如果N 是一个数组,那么您想在给定数组维度的情况下构建一个零数组,对吗?在这种情况下,键将是数组维度的tuple(可散列)。如果需要数组的内容,那就很难了……
  • 是的,我需要二维输入数组的内容来构建二维输出数组:/
  • 也许可以以lru_cache 的方式构建一个自制的装饰器。但是,它不会像lru_cache 那样使用键值系统,而是会一一解析所有先前的输入。如果缓存输入的数量不是太多,它可能会起作用。
  • 如果将相同的二维输入数组传递给您的函数(并且您不复制这些数组),您可以使用 id 作为字典的键(以识别现有对象) .这是第一个示例中的一个微不足道的变化(也适用于小整数,因为它们在 CPython 中从 -5 到 256 是唯一的)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-19
  • 1970-01-01
  • 2017-09-20
  • 2017-04-29
  • 2021-03-26
  • 1970-01-01
相关资源
最近更新 更多