Gestión de memoria (VIII)

Introducción

En un post anterior discutíamos la importancia de garantizar la localidad espacial y temporal de nuestros programas, dado el modo de funcionamiento de la jerarquía de memoria. Analizaremos aquí un test clásico que demuestra la latencia asociada al acceso a niveles inferiores de dicha jerarquía mediante el empleo simple de una matriz cuadrada 2-dimensional de enteros, de tamaño N = L1Size/sizeof(int), cuyas filas encajen en la memoria caché L1. La representación en memoria de dicha matriz puede lograrse a través de un vector std::vector<int>(N*N) de elementos contiguos en memoria o, si el tamaño de la pila de usuario lo permitiese, un array de arrays std::array<std::array<int,N>,N>{}. En ambos casos, asumiremos la representación Row-major propia de C y C++, en la que las entradas de una misma fila son adyacentes en memoria.
Nota: En un orden Row-mayor, la matriz 
      [1 2 3]
[A] = [4 5 6]
      [7 8 9] 
queda representada en memoria como la secuencia [1 2 3 4 5 6 7 8 9]. Comparemos esta representación con la obtenida con un orden de tipo Column-major:[1 4 7 2 5 8 3 6 9].