Fun home 1 |
Como en cualquier otra actividad, programar requiere seguir reglas para ser efectivo. Del mismo modo en que deberíamos limpiar nuestro cuarto de vez en cuando; debemos economizar la memoria de la computadora.
Por ello, en esta entrada, platicaré de las bases de la preasignacion de memoria (memory preallocation) en Matlab. La preasignación de memoria es una práctica excelente de programación que SIEMPRE debemos seguir.
¿De qué trata la preasignación de memoria en Matlab?
A diferencia de los otros lenguajes de programación, como C; Matlab “cuida” de la asignación de memoria automáticamente. Así cuando ejecutas un programa, Matlab reserva espacios de memoria para los datos de todas las variables que se utilizan. Y esto se basa en información local, de un modo similar como en el caso de los tipos de datos o el espacio necesario para todos los elementos. Veamos un ejemplo con código Matlab:
X = 1:100;
Y = cos(X);
En la línea 1, Matlab identifica que X es un vector compuesto de 100 elementos de formato doble. Entonces reserva la memoria necesaria para cuando se emplee.
En la línea 2, Y es del mismo tamaño que X, de modo que Matlab reserva memoria antes de llenar el espacio con la información de la función cos(X).
Una consecuencia de este mecanismo es que CADA VEZ que se le pide a Matlab almacenar un nuevo conjunto de datos, Matlab realiza el proceso de asignar algo de memoria. Por ejemplo:
X = 1:100;
X(101) = 1;
En este ejemplo, X está compuesto inicialmente de 100 elementos; luego cuando se le ordena a Matlab que llene el elemento 101, implícitamente se le pide a Matlab que reasigne algo de memoria para que se pueda incluir el nuevo elemento de X.
¿Por qué tanto alboroto con la preasignación de memoria?
Para todos los datos en una matriz, Matlab requiere un proceso de memoria continua. Como resultado, si el espacio de memoria para el espacio 101 es solicitado; entonces Matlab copia todos los valores originales de X y los coloca en un nuevo sitio donde hay espacio para hasta los 101 elementos.
Veamos un ejemplo más extremo, si X esta hecho 100 mil elementos en lugar de 100, el tamaño de memoria para X es grande y estos grandes espacios de memoria no son tan fáciles de localizar. Es como querer estacionar un autobús turístico en el centro de la ciudad… toma bastante tiempo.
Es especialmente en los ciclos for cuando este proceso de asignación de memoria es notorio. Por ejemplo en esta rutina (script) al que llame ejemplo_memoria0:
for i=1: 100000
Y(i)=cos(i);
end
En este caso, a cada paso en el ciclo for, se le pide a Matlab que añada un elemento a la matriz Y. De hecho, se le pide a Matlab que engrose a Y en memoria a cada paso.
Al principio del proceso, es fácil y rápido; pues Y es pequeño. Pero a medida que progresa el ciclo, Y se hace cada vez más grande, de modo que Matlab debe encontrar espacios de memoria mucho más grandes. Por lo que se vuelve una pesadilla de asignare
La solución es simple: preasignación de memoria
La idea se basa en que tú sabes de antemano cual será el tamaño del vector, por ello se lo debes comunicar a la computadora antes de que entre en el ciclo for. Por ejemplo, la mayoría de las personas utilizan funciones como ones o zeros de este modo:
Ahora, se puede aumentar la velocidad un poco más. En lugar de gastar el tiempo llenado con ceros una matriz, se le puede pedir a Matlab que llene solamente el último elemento de un vector. Por ejemplo:
La solución es simple: preasignación de memoria
La idea se basa en que tú sabes de antemano cual será el tamaño del vector, por ello se lo debes comunicar a la computadora antes de que entre en el ciclo for. Por ejemplo, la mayoría de las personas utilizan funciones como ones o zeros de este modo:
Y = zeros(100000,1);
for i= 1:100000
Y(i) = cos(i);
end
En mi computadora viejita y sobre-explotada, la primera versión tarda: 21.6511 s; y utilizando la pre-asignación de memoria tarda en ejecutarse: 0.009333 s. Es decir, estos cambios significaron que: ¡¡~688 VECES AUMENTÓ LA VELOCIDAD DEL CÁLCULO!!
Ahora, se puede aumentar la velocidad un poco más. En lugar de gastar el tiempo llenado con ceros una matriz, se le puede pedir a Matlab que llene solamente el último elemento de un vector. Por ejemplo:
Y (100000) =0;
for i= 1:100000
Y(i) = cos(i);
end
En este último caso, la rutina tardo 0.009074 s. Este ahorro de tiempo es especialmente significativo cuando se construyen diversas matrices de gran tamaño.
Preguntas para pensar:
1) ¿Cuáles otras prácticas de programación se deben emplear para aumentar la eficiencia de nuestros programas?
Ejercicios
1) En la línea de comandos de Matlab, yo utilicé los siguientes comandos para medir el tiempo de ejecución de mi rutina:
clear, tic; ejemplo_memoria0; disp( ['se tardo ' num2str(toc) 's.'] );
a) ¿Qué hace los comandos tic y toc?
b) En este caso, ¿Por qué es necesario transformar un número en cadena de caracteres?
c) Crea una tabla con los tres ejemplos mostrados en esta entrada donde se muestre la diferencia de velocidades en los procesos de cálculo,
No hay comentarios:
Publicar un comentario