• No results found

él. Como normalmente se accede a las instrucciones secuencialmente, los programas muestran mucha localidad espacial: por ejemplo, los accesos a los elementos de un vector. La localidad espacial ha sugerido la creación y diseño de la memoria de forma jerárquica. Una jerarquía de memoria consiste en múltiples niveles de memoria con diferentes velocidades y capacidad. Las memorias se construyen con jerarquías de niveles: más cercanas las más rápidas (que son también las más caras) y más lejanas las más lentas (que son también las más baratas). A las más cercanas son a las que llamamos memoria caché: caché fue el término escogido para representar el nivel de la jerarquía de memorias entre la CPU y la memoria principal.

Todos los datos se guardan en el nivel más bajo o lejano. Los niveles tienen un tiempo de acceso mayor cuanto más lejos del procesador estén. Entre niveles se transfieren bloques de información. Los datos se transfieren solo entre niveles adyacentes.

Diremos que hemos tenido un acierto si los datos que pide el procesador aparecen en algún bloque del nivel superior. Diremos que hemos tenido un fallo de acceso a memoria si los datos no se encuentran en el nivel superior. En este caso se debe acceder al nivel inferior para leer el bloque que contiene los datos deseados.

Por razón del rendimiento, la velocidad de los aciertos y de los fallos es importante. El tiempo de acierto es el tiempo necesario para acceder al nivel superior de la jerarquía. La penalización del fallo es el tiempo necesario para reemplazar un bloque del nivel superior por el correspondiente bloque del nivel inferior mas el tiempo de suministrar ese bloque al procesador.

3.5.1.1. Cómo aprovechar la localidad espacial.

Para la gestión de fallos, la propuesta básica es parar la CPU, congelando los valores de todos los registros. Un controlador separado se encarga del fallo de caché, buscando los datos en la memoria. Una vez que los datos están presentes, la ejecución se reanuda en el ciclo que ha causado el fallo de caché. Así, el procesamiento de un fallo de caché provoca un bloqueo del

Conceptos básicos del rendimiento de un computador 63 procesador.

Existen modos de paliar el retardo que ocasiona un fallo de acceso a memoria. Uno de ellos es aprovechar la localidad espacial de los accesos a memoria. Para ello es bueno tener un bloque de caché mayor que una palabra. En caso de fallo, se buscarán múltiples palabras que sean adyacentes y conlleven una alta probabilidad de ser referenciadas en breve. El motivo del incremento del tamaño del bloque es sacar partido a la localidad espacial para incrementar el rendimiento. En general la tasa de fallo desciende cuando se incrementa el tamaño del bloque. La tasa de fallos podría crecer si el tamaño del bloque es una parte significativa del tamaño de la caché porque el número de bloques que pueden estar en la caché sería entonces pequeño y, por tanto, habría una fuerte competencia entre esos bloques.

El mayor inconveniente de aumentar el tamaño del bloque es que la penalización por fallo crece. 3.5.1.2. Cómo medir y mejorar el rendimiento de la caché.

Presentamos dos técnicas para reducir la tasa de fallos:

1. Reducir la tasa de fallos reduciendo la posibilidad de que dos bloques diferentes de memoria vayan a la misma posición de la caché.

2. Reducir la penalización por fallo añadiendo un nivel adicional en la jerarquía: caché multinivel. Podemos hablar habitualmente de dos niveles de caché: la memoria L1 más cercana, y la memoria L2.

El tiempo de la CPU se puede dividir entre el número de ciclos en los que la CPU ejecuta el programa y el número de ciclos en los que la CPU espera la memoria. Normalmente se supone que el coste de los accesos a la caché que son aciertos son parte de los ciclos de ejecución normal de la CPU. Por tanto

Tiempo de CPU = ( Ciclos de ejecución de la CPU + Ciclos de bloqueo por memoria ) * de ciclo Tiempo Los ciclos de bloqueo causados por memoria son principalmente debidos a fallos de caché, y así se puede asumir en adelante.

Ciclos de bloqueo por

memoria = Ciclos de bloqueo por lectura + Ciclos de bloqueo por escritura

Lecturas Ciclos de bloqueo

por lectura = Programa * Tasa de fallos por lectura * Penalización por fallos de lectura

Despreciando las penalizaciones por escritura en buffer tenemos que los ciclos de bloqueo por escritura son

Escrituras Ciclos de bloqueo

por escritura = Programa *

Tasa de fallos por escritura *

Penalización por fallos de escritura

Conceptos básicos del rendimiento de un computador 64 Y los ciclos de bloqueo por memoria nos quedan entonces

Accesos a memoria Ciclos de bloqueo

por memoria = Programa * Tasa de fallos *

Penalización por fallo 1. Cuanto más bajo sea el CPI, más pronunciado será el efecto de los ciclos de bloqueo.

2. El sistema de memoria es improbable que mejore tan rápidamente como el tiempo de ciclo del procesador. Cuando se calcula el CPI, la penalización por fallo se mide en ciclos de CPU gastados por fallo. Por tanto, si las memorias principales de dos máquinas tienen el mismo tiempo absoluto de acceso, una CPU con un reloj más rápido tendrá una penalización por fallo más larga.

3.5.1.3. Algunas técnicas de optimización de los accesos a memoria.

Prefetching: Cuando un procesador necesita una variable lo que hace es buscarla en

memoria. Antes (hasta el año 1994), la memoria (como hemos visto) era bloqueante. A partir de 1994 aparecieron los primeros procesadores con buffers de cargas y almacenamientos. Estas dos operaciones no bloquean al resto de operaciones, y el procesador puede seguir realizando instrucciones mientras se espera la llegada de algunos datos. Evidentemente, esto exige que las operaciones que ejecute mientras se espera no requieran la información que está llegando.

El caso es que no hay tanto buffer de memoria, y no es fácil tener muchas instrucciones en vuelo de carga–almacenamiento. Además, si disponemos de pocas instrucciones de otra naturaleza que no sea carga–almacenamiento, al final el proceso se queda bloqueado en la espera de datos. Y aquí es donde entra la tarea del prefetching.

Cada vez que el procesador acude a memoria L1 y no halla en ella la información que requiere pasa a buscar el L2, y si no, en la memoria principal. Cada vez que acude a la memoria principal, aprovecha el proceso y se trae una cierta cantidad de bytes de información siguientes.

Declarando bien las variables ya podemos ganar tiempo. Habitualmente el procesador almacena de modo consecutivo las variables que han sido declaradas de forme consecutiva. Y ya se sabe que los arrays se almacenan linealmente.

Lo que hace el prefetching es buscar las variables antes de su uso. Y se hace con algunas que se supone que estarán fuera de las líneas de caché. El prefetching no reduce los fallos de caché: pero enmascara el tiempo que invierte en acudir a esa memoria. El proceso será bueno si acertamos en los momentos en los que es conveniente hacer el prefetching.

⇒ Mezcla de vectores: Esta y las siguientes tareas lo que pretenden es explotar la localidad espacial de las variables en la memoria. Se trata de trabajar varios vectores en un mismo bucle. Se trata de unir variables.

Conceptos básicos del rendimiento de un computador 65 Este método tiene interés en el caso en el que no se recorra el vector elemento a elemento. En ese caso, podríamos mezclar vectores para poder traer (cada vez que se vaya a memoria principal) información toda ella útil.

⇒ Intercambio de bucles: A veces podemos estar recorriendo los bucles de forma inversa a como está almacenado en memoria. Una vez más el objetivo es que cada vez que tenga un fallo de caché trabajar de forma que todo lo que me traiga a L1 sea información que utilizaré de forma inmediata.

⇒ Fusión de bucles: Fundir dos bucles en uno solo. Esto es útil cuando tengo dos bucles que siguen el trazo sobre el mismo vector.

Blocking: Trabajar por trozos o bloques. Para aprovechar la localidad espacial de la memoria.

El objetivo es hacer trozos que quepan en la caché y que guarden entre sí todas las relaciones necesarias para las operaciones que deseo realizar.

Variables register: Quedan recogidas en el registro de la ALU.

Una nueva implementación de entero largo para procesos de factorización 67

4

ENTERO LARGO PARA PROCESOS DE UNA NUEVA IMPLEMENTACIÓN DE