我在MATLAB中有很重要的功能:
function [out] = f ( in1, in2, in3)
使用相同的参数经常调用它。 该函数是确定性的,因此对于给定的输入参数,其输出将始终相同。
在函数中存储计算输入结果的最简单方法是什么?如果使用相同的输出再次调用该函数,它将能够快速回答?
是一个持久变量,它将(使用containers.Map
或其他类)输入集<in1, in2, in3>
映射到结果的路径?
请注意,在我的应用程序中,任何需要将数据保存到磁盘的方法都是不可能的。
答案 0 :(得分:7)
以下是CacheableFunction类的想法
班级定义
classdef CacheableFunction < handle
properties
exeFun
hashFun
cacheMap
nOutputs
zipOutput
end
methods
function obj = CacheableFunction(exeFun, hashFun, nOutputs)
obj.exeFun = exeFun;
obj.hashFun = hashFun;
obj.cacheMap = containers.Map;
obj.nOutputs = nOutputs;
obj.zipOutput = [];
end
function [result] = evaluate(obj, varargin)
thisKey = obj.hashFun(varargin);
if isKey(obj.cacheMap, thisKey)
if obj.zipOutput
result = cellfun(@(x) dunzip(x), obj.cacheMap(thisKey), 'UniformOutput', false);
else
result = obj.cacheMap(thisKey);
end
else
[result{1:obj.nOutputs}] = obj.exeFun(varargin);
if isempty(obj.zipOutput)
obj.zipCheck(result);
end
if obj.zipOutput
obj.cacheMap(thisKey) = cellfun(@(x) dzip(x), result, 'UniformOutput', false);
else
obj.cacheMap(thisKey) = result;
end
end
end
function [] = zipCheck(obj,C)
obj.zipOutput = all(cellfun(@(x) isreal(x) & ~issparse(x) & any(strcmpi(class(x), ...
{'double','single','logical','char','int8','uint8',...
'int16','uint16','int32','uint32','int64','uint64'})), C));
end
end
end
测试出来......
function [] = test_caching_perf()
A = CacheableFunction(@(x) long_annoying_function(x{:}), @(x) DataHash(x), 3);
B = rand(50, 50);
C = rand(50, 50);
D = rand(50, 50);
tic;
myOutput = A.evaluate(B, C, D);
toc
tic;
myOutput2 = A.evaluate(B, C, D);
toc
cellfun(@(x, y) all(x(:) == y(:)), myOutput, myOutput2)
end
function [A, B, C] = long_annoying_function(A, B, C)
for ii = 1:5000000
A = A+1;
B = B+2;
C = C+3;
end
end
结果
>> test_caching_perf
Elapsed time is 16.781889 seconds.
Elapsed time is 0.011116 seconds.
ans =
1 1 1
答案 1 :(得分:6)
MATLAB现在附带了一个仅用于此目的的功能。 使用的技术称为“memoization”,函数名称为“memoize”。
答案 2 :(得分:5)
持久映射确实是实现缓存结果的好方法。我能想到的优点:
有一个文件交换提交,由David Young提供A multidimensional map class,附带一个函数memoize()正是这样做的。它的实现使用了一种不同的机制(引用的局部变量),但这个想法大致相同。与每个函数内部的持久映射相比,这个memoize()函数允许现有函数被记忆而无需修改。正如Oleg所指出的,使用DataHash(或等效的)可以进一步减少内存使用量。
PS:我已经广泛使用了MapN类,它非常可靠。实际上我已经提交了一份错误报告,作者及时修复了它。