内存化是一种技术,用于缓存慢速函数调用的结果,并在使用相同的输入再次调用函数时返回缓存的值,而不是重新评估它。如果相同的输入以已知的、可预测的方式一次又一次地发生,则用查找表替换函数调用是非常常见的。Memoization的核心是这种做法的扩展,即使在运行时,也会为以前没有见过的新参数扩展查找表。一个基本的理论背景可以在维基百科或任何本科水平的计算机科学教科书上找到。
Octave的memoize
函数为任何用户函数或Octave函数(包括已编译的函数)提供插入式存储函数。
mem_fcn_handle =
memoize (fcn_handle)
¶创建备忘录版本mem_fcn_handle的函数fcn_handle.
每次调用备忘录版本mem_fcn_handle在内部维护的表中检查输入,如果输入以前发生过,则从表本身返回函数调用的结果,而不是再次评估整个函数。这加快了使用相同输入多次调用的函数的执行速度。
例如,这里我们使用一个名为slow_fcn
并将其内存到一个新的句柄cyc
两个版本的第一次执行花费相同的时间,但随后执行的memorydepression返回先前计算的值,从而将2.4秒的运行时间减少到仅2.4毫秒。最后的检查验证两个版本是否返回了相同的结果。
>> tic; p = slow_fcn (5040); toc Elapsed time is 2.41244 seconds. >> tic; p = slow_fcn (5040); toc Elapsed time is 2.41542 seconds. >> cyc = memoize (@slow_fcn); >> tic; r = cyc (5040); toc Elapsed time is 2.42609 seconds. >> tic; r = cyc (5040); toc Elapsed time is 0.00236511 seconds. >> all (p == r) ans = 1
内存函数z = foo(x, y)
,使用以下通用模式:
foo2 = memoize (@(x, y) foo(x, y)); z = foo2 (x, y);
在上面的例子中,第一行创建了一个内存版本foo2
的函数foo
。对于只有琐碎软件包的简单函数,这一行也可以缩短为:
foo2 = memoize (@foo);
第二行z = foo2 (x, y);
调用那个内存版本foo2
而不是原来的函数,允许memoize
截取调用并将其替换为表中查找到的值(如果输入以前发生过),而不是再次评估原始函数。
请注意,这不会加速第一对函数的调用,但仅限于后续调用。
请注意,因为memoize
要为每个函数创建和管理查找表,此技术仅适用于至少需要几秒钟执行时间的函数。这样的函数可以被只需要一毫秒左右的表查找所取代,但如果原始函数本身只需要几毫秒,那么内存它不会加快速度。
递归函数也可以使用如下模式进行内存:
function z = foo (x, y) persistent foo2 = memoize (@foo); foo2.CacheSize = 1e6; ## Call the memoized version when recursing z = foo2 (x, y); endfunction
这里的CacheSize
可以在预期大量函数调用时(例如从递归函数内部)选择性地增加。如果CacheSize
如果超过,则调整存储表的大小,从而导致停机。增加CacheSize
因此,其起作用方式类似于预赋值,以加快执行速度。
函数clearAllMemoizedCaches
当不再需要内存表时,清除它们。
()
¶清除所有已存储的缓存。
内存化维护内部表,其中哪些函数被调用,哪些输入被调用。此函数用于清除这些表以释放内存,或重新启动。
详见: memoize.
版权所有 © 2024-2025 Octave中文网
ICP备案/许可证号:黑ICP备2024030411号-2