El principio de localidad

Este principio, muy conocido, pero no siempre bien utilizado por desarrolladores y diseñadores, tiene dos vertientes:

  • Localidad Espacial: Tendencia a referenciar elementos de memoria cercanos a los últimos que han sido referenciados.
  • Localidad Temporal: Tendencia a referenciar elementos de memoria que han sido referenciados recientemente.

En los programas la localidad surge de las estructuras más sencillas y naturales. Por ejemplo, un bucle es una estructura en la que es sencillo explotar la localidad temporal, los bloques de código que se ejecutan secuencialmente hacen que sea fácil explotar la localidad espacial, etc.

La jerarquía de memoria tiene sentido gracias al pricipio de localidad. El procesador encuentra muy a menudo en la memoria caché los datos que referencia (a pesar del reducido tamaño de esta memoria), porque en esta memoria están los datos e instrucciones que ha utilizado recientemente y los que están cercanos a ellos.

Pero para que el funcionamiento de la jerarquía sea óptimo, los códigos y compiladores deben tener en cuenta el principio de localidad. Si por ejemplo, los elementos de una matriz se almacenan en memoria por filas, un código que accediera por filas a la matriz estaría aprovechando la localidad mientras que un código que lo hiciera por columnas estaría provocando constantes fallos de memoria y empeorando considerablemente los tiempos de ejecución.

Conclusión: cuidado con los patrones de acceso de vuestros códigos a memoria, pueden ser un factor muy importante en el rendimiento final que obtengáis al ejecutarlos. Para empezar, es un buena práctica conocer el tamaño exacto de los diferentes niveles de caché de vuestro procesador y así estimar el tamaño óptimo de los bloques de información con los que trabajáis.

La instrucción de ensamblador CPUID permite obtener esta información, os dejo este enlace para que podáis descargar benchmarks sencillos basados en ella y así poder caracterizar vuestra jerarquía de memoria:

http://www.cpuid.com/
aaa