存储函数值以防止再次运行

时间:2020-07-12 06:31:17

标签: function integration numeric numerical-computing

说我有一些复杂的功能f(fvar1, ..., fvarN),例如:

def f(fvar1,..., fvarN):
    return (complicated function of fvar1, ..., fvarN).

现在函数g(gvar1, ..., gvarM)的表达式为f(fvar1, ..., fvarN),可以这样说:

def g(gvar1, ..., gvarM):
    return stuff * f(gvar1 * gvar2, ..., gvar5 * gvarM) - stuff * f(gvar3, gvar2, ..., gvarM)

fg的自变量可以是gvar1, ..., gvarM的不同线性组合。

由于f是一个复杂的函数,因此调用f的开销很大,但是由于g有很多实例,因此很难将值本地存储在gf具有不同的参数组合。

是否有一种方法可以存储 f的值,从而不必一次又一次调用具有相同值的f,而不必定义{{ 1}}在f中本地?

1 个答案:

答案 0 :(得分:1)

是的,这称为记忆。基本思想是让</html>根据传入的参数维护某种数据存储。然后,如果使用 same 参数进行调用,则它只是返回存储的值,而不是重新计算它。

通过基于某些规则删除参数集,可能需要限制数据存储的大小并针对您期望的调用模式进行优化。例如,如果使用参数集的次数 表示其将来可能使用,则您可能希望删除不经常使用的模式,并保留更经常使用的模式。 / p>

例如,考虑以下用于将两个数字相加的Python代码(让我们假装这是一个非常耗时的操作):

f()

可以,但是,如果使用与以前使用的相同的数字,则效率很低。您可以按如下所示添加便笺。

该代码将“记住”一定数量的计算(给定字典,可能是随机的,但我不能保证)。如果它已经已经知道知道的一对,它只会返回缓存的值。

否则,它计算值,将其存储到缓存中,并确保所述缓存不会变得太大:

import random

def addTwo(a, b):
    return a + b

for _ in range(100):
    x = random.randint(1, 5)
    y = random.randint(1, 5)
    z = addTwo(x, y)
    print(f"{x} + {y} = {z}")

您将看到我还添加了缓存/计算的信息,包括最后一个统计行,该行显示了正在执行的缓存,例如:

import random, time

# Cache, and the stats for it.

(pairToSumMap, cached, calculated) = ({}, 0, 0)

def addTwo(a, b):
    global pairToSumMap, cached, calculated

    # Attempt two different cache lookups first (a:b, b:a).

    sum = None
    try:
        sum = pairToSumMap[f"{a}:{b}"]
    except:
        try:
            sum = pairToSumMap[f"{b}:{a}"]
        except:
            pass

    # Found in cache, return.

    if sum is not None:
        print("Using cached value: ", end ="")
        cached += 1
        return sum

    # Not found, calculate and add to cache (with limited cache size).

    print("Calculating value: ", end="")
    calculated += 1

    time.sleep(1) ; sum = a + b # Make expensive.

    if len(pairToSumMap) > 10:
        del pairToSumMap[list(pairToSumMap.keys())[0]]
    pairToSumMap[f"{a}:{b}"] = sum
    return sum

for _ in range(100):
    x = random.randint(1, 5)
    y = random.randint(1, 5)
    z = addTwo(x, y)
    print(f"{x} + {y} = {z}")

print(f"Calculated {calculated}, cached {cached}")

我也使计算成为昂贵的操作,因此您可以看到它的实际效果(根据输出速度)。缓存的内容将立即返回,计算总和将需要一秒钟。