Main Content

本页翻译不是最新的。点击此处可查看最新英文版本。

memoize

向函数句柄添加储存语义

说明

储存是一种优化技术,可通过缓存开销较大的函数调用的结果,并在使用相同的输入调用程序时返回缓存的结果,来提高程序运行速度。

如果满足以下所有条件,可考虑储存函数调用:

  • 性能非常重要。

  • 函数非常耗时。

  • 函数的返回值完全由输入值确定,并且没有意外结果。

  • 系统内存足以存储唯一的输入和输出组合。

示例

memoizedFcn = memoize(fh) 向输入函数句柄添加储存语义,并返回 MemoizedFunction 对象。就像调用 fh 一样调用 memoizedFcn。但 memoizedFcn 不是函数句柄。

MemoizedFunction 对象维护输入和对应输出的缓存。在调用 MATLAB® 时,如果满足以下条件,它会返回关联的缓存输出值。

  1. 输入参数在数值上等于缓存的输入。在比较输入值时,MATLAB 将 NaN 值视为相等的值。

  2. 请求的输出参数的数量与输入所关联的缓存输出的数量相匹配。

函数的储存与输入函数关联,与 MemoizedFunction 对象无关联。因此,请牢记以下事项。

  • 对同一函数构造新的 MemoizedFunction 对象将创建对相同数据的另一个引用。储存同一个函数的两个变量可共享缓存和对象属性值,如缓存大小。在以下示例中,变量 ab 共享缓存并具有相同的缓存大小值。

    a = memoize(@svd);
    b = memoize(@svd);
    类似地,清除 b (b.clearCache) 的缓存还将清除对 a 以及用来储存 svd 函数的任何其他变量的缓存。clearCache 是一个 MemoizedFunction 对象函数。

  • MemoizedFunction 对象分配给新变量将创建对相同数据的另一个引用。在以下示例中,变量 cd 共享数据。

    c = memoize(@svd);
    d = c;

  • 清除变量并不会清除与输入函数关联的缓存。要清除工作区中不再存在的 MemoizedFunction 对象的缓存,请为同一个函数创建一个新的 MemoizedFunction 对象,然后对新对象使用 clearCache 函数。您也可以使用 clearAllMemoizedCaches 函数清除所有 MemoizedFunction 对象的缓存。

小心

MemoizedFunction 对象并不知道基础函数的更新。如果您修改与储存的函数关联的函数,请使用 clearCache 对象函数清除缓存。

示例

全部折叠

当您可能多次对相同输入进行运算时,为了加快执行奇异值分解的速度,可以储存 svd 函数。

fh = @svd;
memoizedFcn = memoize(fh);

创建一个矩阵并缓存奇异值分解的结果。记录函数调用的时间。

X = magic(1234);
tic
[U,S,V]= memoizedFcn(X);
preCachedTime = toc
preCachedTime = 0.4655

使用相同的输入再次调用储存的函数。要观察使用缓存的结果后的速度提升,请再次记录函数调用的时间。

tic
[U,S,V]= memoizedFcn(X);
postCachedTime = toc
postCachedTime = 0.0038

在当前工作文件夹中创建一个文件 computeNumberCombinations.m,它包含以下函数以计算从 n 项中一次取 k 项的组合的数目。

type computeNumberCombinations.m
function c = computeNumberCombinations(n,k)
% Calculate number of combinations of n items taken k at a time
c = fact(n)/(fact(n-k)*fact(k));
end

function f = fact(n)
f = 1;
for m = 2:n
    f = f*m;   
end
end

清除工作区中任何 MemoizedFunction 对象的缓存。

clearAllMemoizedCaches

储存 computeNumberCombinations 函数以提高重复输入值的计算速度。

fh = @computeNumberCombinations;
memoizedFcn = memoize(fh);

调用储存的函数并记录函数调用的时间。此函数调用会缓存指定输入的结果。

tic
c = memoizedFcn(42e5,137);
preCachedTime = toc
preCachedTime = 0.0212

再次调用记住的函数并记录函数调用的时间。此函数调用使用缓存的结果,并且不执行该函数。

tic
c = memoizedFcn(42e5,137);
postCachedTime = toc
postCachedTime = 0.0035

输入参数

全部折叠

要储存的函数,指定为函数句柄。

示例: memoizedEigs = memoize(@eigs)

数据类型: function_handle

提示

  • 使用相同的函数句柄多次调用 memoize 将返回相同的 MemoizedFunction 对象。例如:

    x = memoize(@plus);
    y = memoize(@plus);
    x == y
    ans =
    
      logical
    
       1
  • 您不应储存具有意外结果的函数,例如设置某些全局状态或执行 I/O 操作。这样在以后使用相同输入调用储存的函数时,才不会重复意外结果。例如,如果您储存 randi 函数,在使用相同的输入参数调用时,储存的函数会始终返回相同的值。

    fh = @randi;
    memoized_fh = memoize(fh);
    
    fh_result = [fh(100) fh(100) fh(100)]
    memoized_result = [memoized_fh(100) memoized_fh(100) memoized_fh(100)]
    fh_result =
    
        18    71     4
    
    
    memoized_result =
    
        28    28    28

版本历史记录

在 R2017a 中推出