tag que informatica performance x86 virtual-memory tlb

performance - que - ¿En qué circunstancias pueden las páginas grandes producir una aceleración?



que es title en informatica (5)

Esto se está volviendo esotérico, pero las páginas de TLB enormes marcan una diferencia significativa en la arquitectura Intel Xeon Phi (MIC) al realizar transferencias de memoria DMA (de Host a Phi a través de PCIe). Este enlace de Intel describe cómo habilitar páginas grandes . Descubrí que el aumento de los tamaños de transferencia DMA más allá de 8 MB con el tamaño de página normal de TLB (4K) comenzó a disminuir el rendimiento, de aproximadamente 3 GB / s a ​​menos de 1 GB / s una vez que el tamaño de transferencia alcanzó los 512 MB.

Después de habilitar enormes páginas TLB (2 MB), la velocidad de datos continuó aumentando a más de 5 GB / s para transferencias DMA de 512 MB.

Las CPU x86 modernas tienen la capacidad de admitir tamaños de página más grandes que los 4K heredados (es decir, 2MB o 4MB), y existen instalaciones de SO ( Linux , Windows ) para acceder a esta funcionalidad.

El enlace de Microsoft anterior indica que las páginas grandes "aumentan la eficiencia del búfer de traducción, lo que puede aumentar el rendimiento de la memoria de acceso frecuente". Lo que no es muy útil para predecir si las páginas grandes mejorarán una situación determinada. Me interesan los ejemplos concretos, preferiblemente cuantificados, en los que mover alguna lógica del programa (o toda una aplicación) para usar páginas grandes ha dado como resultado una mejora en el rendimiento. ¿Alguien tiene alguna historia de éxito?

Hay un caso particular que conozco de myself : el uso de páginas grandes puede reducir dramatically el tiempo necesario para un proceso grande (presumiblemente, ya que el número de registros de TLB que necesitan copiarse se reduce en un factor del orden de 1000). Me interesa si las páginas grandes también pueden ser un beneficio en escenarios menos exóticos.


He visto mejoras en algunos escenarios de HPC / Grid, específicamente paquetes de física con modelos muy grandes en máquinas con mucha y mucha RAM. También el proceso de ejecución del modelo fue lo único activo en la máquina. Sospecho, aunque no lo he medido, que ciertas funciones de DB (por ejemplo, importaciones a granel) también se beneficiarían.

Personalmente, creo que a menos que tenga un perfil de acceso a la memoria muy bien perfilado / comprendido y tenga un gran acceso a la memoria, es poco probable que vea una mejora significativa.


La mayor diferencia en el rendimiento se producirá cuando realice accesos aleatorios ampliamente espaciados a una gran región de la memoria, donde "grande" significa mucho más grande que el rango que se puede asignar mediante todas las entradas de páginas pequeñas en los TLB (que generalmente Disponemos de múltiples niveles en procesadores modernos).

Para hacer las cosas más complejas, el número de entradas de TLB para páginas de 4kB suele ser mayor que el número de entradas para páginas de 2MB, pero esto varía mucho según el procesador. También hay una gran cantidad de variaciones en la cantidad de entradas de "página grande" que están disponibles en el TLB de Nivel 2.

Por ejemplo, en un sistema AMD Opteron Family 10h Revisión D ("Estambul"), cpuid informa:

  • L1 DTLB: 4kB páginas: 48 entradas; Páginas de 2MB: 48 entradas; 1GB páginas: 48 entradas
  • L2 TLB: 4kB páginas: 512 entradas; Páginas de 2MB: 128 entradas; 1GB páginas: 16 entradas

Mientras se encuentra en un sistema Intel Xeon 56xx ("Westmere"), cpuid informa:

  • L1 DTLB: 4kB páginas: 64 entradas; Páginas de 2MB: 32 entradas.
  • L2 TLB: 4kB páginas: 512 entradas; Páginas de 2MB: ninguna

Ambos pueden asignar 2MB (512 * 4kB) usando páginas pequeñas antes de sufrir pérdidas de TLB de nivel 2, mientras que el sistema Westmere puede asignar 64MB usando sus entradas de 32BMB de TLB y el sistema de AMD puede asignar 352MB utilizando las entradas de TLB de 176 MB en su L1 y L2 TLBs. Cualquiera de los sistemas obtendrá una importante aceleración al usar páginas grandes para accesos aleatorios en rangos de memoria que son mucho más grandes que 2 MB y menos de 64 MB. El sistema AMD debería continuar mostrando un buen rendimiento al usar páginas grandes para rangos de memoria mucho más grandes.

Lo que intenta evitar en todos estos casos es el peor de los casos (nota 1) de atravesar los cuatro niveles de la traducción de direcciones jerárquica x86_64.
Si ninguno de los mecanismos de almacenamiento en caché de traducción de direcciones (nota 2) funciona, se requiere:

  • 5 viajes a la memoria para cargar datos asignados en una página de 4kB,
  • 4 viajes a la memoria para cargar datos asignados en una página de 2MB, y
  • 3 viajes a la memoria para cargar datos asignados en una página de 1GB.

En cada caso, el último viaje a la memoria es obtener los datos solicitados, mientras que los otros viajes son necesarios para obtener las diversas partes de la información de traducción de la página. La mejor descripción que he visto está en la Sección 5.3 del "Volumen 2 del Manual del Programador de Arquitectura AMD64 de AMD" (Programación del sistema) (publicación 24593) http://support.amd.com/us/Embedded_TechDocs/24593.pdf

Nota 1: Las cifras anteriores no son realmente el peor de los casos. Correr bajo una máquina virtual empeora estos números. La ejecución en un entorno que hace que la memoria que contiene los distintos niveles de las tablas de páginas se cambie al disco empeora el rendimiento.

Nota 2: Desafortunadamente, incluso saber este nivel de detalle no es suficiente, porque todos los procesadores modernos tienen cachés adicionales para los niveles superiores de la jerarquía de traducción de la página. Por lo que sé, estos están muy mal documentados en público.


Obtengo un ~ 5% de aceleración en servidores con mucha memoria (> = 64GB) ejecutando grandes procesos. Por ejemplo, para un proceso Java de 16 GB, son páginas 4M x 4kB pero solo páginas 4k x 4MB.


Intenté crear un código que maximice la agitación del TLB con 4k páginas para examinar las ganancias posibles de las páginas grandes. El material a continuación se ejecuta 2.6 veces más rápido (que las páginas 4K) cuando las páginas de 2MByte son proporcionadas por el malloc de libhugetlbfs (Intel i7, Debian Lenny de 64 bits); scoped_timer que sea obvio lo que hacen scoped_timer y random0n .

volatile char force_result; const size_t mb=512; const size_t stride=4096; std::vector<char> src(mb<<20,0xff); std::vector<size_t> idx; for (size_t i=0;i<src.size();i+=stride) idx.push_back(i); random0n r0n(/*seed=*/23); std::random_shuffle(idx.begin(),idx.end(),r0n); { scoped_timer t ("TLB thrash random",mb/static_cast<float>(stride),"MegaAccess"); char hash=0; for (size_t i=0;i<idx.size();++i) hash=(hash^src[idx[i]]); force_result=hash; }

Una versión más simple de "línea recta" con solo hash=hash^src[i] solo obtuvo un 16% de páginas grandes, pero (la especulación descabellada) el elegante hardware de recuperación previa de Intel puede ayudar al caso de 4K cuando los accesos son predecibles (supongo que podría inhabilitar Previa búsqueda para investigar si eso es cierto).