回答这两个问题的方法是使用地图。这需要几个步骤。
First you will need a function to turn your bit_array into either a number or a string. For example, turn [0 1 1 0 1 0]
into '011010'
. (Matlab only supports scalar or string keys, which is why this step is required.)
Defined a map object
cachedRunMap = containers.Map
To check if a particular case has been run, use iskey
.
cachedRunMap.isKey('011010');
To add the results of a run use the appending syntax
cachedRunMap('011010') = [0 1 1 0 1]; %Or whatever your result is.
To retrieve cached results, use the getting syntax
tmpResult = cachedRunMap.values({'011010'});
这样可以有效地存储和检索数值,直到系统内存不足为止。
将所有内容整合在一起,你的代码现在应该是这个样子:
strFromBits = @(x) char((x(:)'~=0)+48);
cachedRunMap = containers.Map;
for i=1:1000000000
strKey = strFromBits(bit_array);
if cachedRunMap.isKey(strKey)
result = cachedRunMap(strKey);
else
result = complex_function(bit_array);
cachedRunMap(strKey) = reult;
end
end
如果你想要一个不是字符串类型的键,那么需要在步骤2中进行声明。以下是一些例子:
cachedRunMap = containers.Map('KeyType', 'char', 'ValueType', 'any');
cachedRunMap = containers.Map('KeyType', 'double', 'ValueType', 'any');
cachedRunMap = containers.Map('KeyType', 'uint64', 'ValueType', 'any');
cachedRunMap = containers.Map('KeyType', 'uint64', 'ValueType', 'double');
将KeyType
设置为'char'
将使得Map使用字符串作为键,而所有其他类型必须是标量。
关于扩展的问题(根据您最近的评论)
在会话之间保存数据:将此Map保存到*.mat文件中应该没有问题,但也受系统内存限制。
清除旧数据:我不知道如何直接添加LRU功能。如果您可以找到Java实现,那么在Matlab中使用它相当容易。否则,需要考虑最有效地跟踪上次使用key的时间的方法。
在并发会话之间共享数据:正如您所指出的,这可能需要一个数据库来实现高效性。数据库表将有两列(如果您想要实现LRU功能,则为3列),即键、值(和最后使用时间(如果需要)。如果您的“结果”不易适合SQL(例如非统一大小数组或复杂结构),则需要进一步考虑如何存储它。您还需要一种访问数据库的方法(例如,数据库工具箱或Mathworks文件交换中的各种工具)。最后,您需要在服务器上实际设置数据库(例如,如果您像我一样比较节省,您可以使用MySql,或者您有最丰富经验或者能够找到最多帮助的工具)。这实际上并不难,但第一次需要花费一些时间和精力。
另一种考虑的方法(效率低,但不需要数据库)是将数据存储区分为大量(例如1000或数百万个)地图。将每个Map保存到单独的*.mat文件中,文件名基于该Map中包含的键(例如,您字符串键的前N个字符),然后根据需要在会话之间加载/保存这些文件。这将相当缓慢...根据您的使用情况,每次从源函数重新计算可能更快...但这是我可以想到的最好的方法而不设置DB(显然更好的答案)。