round - redondear al entero superior matlab
La forma más limpia de cachear los resultados de las funciones en Matlab (3)
Tengo una función bastante pesada en Matlab
función [out] = f (in1, in2, in3)
Que se llama con bastante frecuencia con los mismos parámetros. La función es determinista, por lo que para los parámetros de entrada dados su salida siempre será la misma.
¿Cuál sería la forma más sencilla de almacenar los resultados de las entradas computadas en la función de modo que si la función se llamará de nuevo con el mismo resultado, podría responder rápidamente?
Es una variable persistente que mapea (usando contenedores.Mapa o alguna otra clase) entrada establecida en un resultado el camino a seguir?
(Cualquier método que requiera guardar los datos en el disco está fuera de cuestión en mi aplicación).
A continuación hay una idea para una clase CacheableFunction
- Parece que todas las respuestas a su pregunta principal apuntan en la misma dirección: un Mapa persistente es la forma consensuada de almacenar en caché los resultados, y yo también lo hago.
- Si las entradas son matrices, deberán pasarse a una cadena o escalar para ser utilizadas como una clave de mapa. Hay muchas formas de agrupar sus 3 matrices de entrada en una clave. Utilicé DataHash en mi solución a continuación.
- Elegí hacer una clase en lugar de una función como memoize para que la función de hash de entrada se pueda especificar dinámicamente una vez, en lugar de codificarse.
- Dependiendo de la forma de su salida, también utiliza dzip / dunzip para reducir la huella de las salidas guardadas.
- Mejora potencial: una manera ingeniosa de decidir qué elementos eliminar del mapa persistente cuando su huella de memoria se acerca a algún límite.
Definición de clase
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
Probando ...
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
Y resultados
>> test_caching_perf
Elapsed time is 16.781889 seconds.
Elapsed time is 0.011116 seconds.
ans =
1 1 1
El mapa persistente es una buena forma de implementar resultados en caché. Ventajas que puedo pensar:
- No es necesario implementar la función hash para cada tipo de datos.
- Las matrices de Matlab son de escritura por copia, que pueden ofrecer cierta eficiencia de memoria.
- Si el uso de la memoria es un problema, se puede controlar cuántos resultados se almacenarán en caché.
Hay una presentación de intercambio de archivos, una clase de mapa multidimensional de David Young, viene con una función memoize () hace exactamente esto. Su implementación usa un mecanismo un poco diferente (variable local referenciada), pero la idea es casi la misma. En comparación con el mapa persistente dentro de cada función, esta función memoize () permite que la función existente sea memorada sin modificaciones. Y como señala Oleg, el uso de DataHash (o equivalente) puede reducir aún más el uso de la memoria.
PD: He usado la clase MapN extensivamente y es bastante confiable. En realidad, he enviado un informe de error y el autor lo solucionó de inmediato.
No reinvente la rueda; lo que está buscando se llama ''Memoization''. Memoria de Matlab de Google, y encontrará algunos resultados útiles. Algunas muestras (no verificaron la validez del código):