GNU/Linux >> Tutoriales Linux >  >> Linux

¿Cómo producir el efecto de caché de la CPU en C y Java?

Esta respuesta no es una respuesta, sino más bien un conjunto de notas.

Primero, la CPU tiende a operar en líneas de caché, no en bytes/palabras/dwords individuales. Esto significa que si lee/escribe secuencialmente una matriz de enteros, el primer acceso a una línea de caché puede causar una pérdida de caché, pero los accesos posteriores a diferentes enteros en esa misma línea de caché no lo harán. Para líneas de caché de 64 bytes y enteros de 4 bytes, esto significa que solo obtendrá una pérdida de caché una vez por cada 16 accesos; lo que diluirá los resultados.

En segundo lugar, la CPU tiene un "buscador previo de hardware". Si detecta que las líneas de caché se leen secuencialmente, el buscador previo de hardware buscará automáticamente las líneas de caché que predice que se necesitarán a continuación (en un intento de recuperarlas en caché antes de que se necesiten).

En tercer lugar, la CPU hace otras cosas (como "ejecución fuera de orden") para ocultar los costos de búsqueda. La diferencia de tiempo (entre el acierto y el error de caché) que puede medir es el tiempo que la CPU no pudo ocultarse y no el costo total de la recuperación.

Estas 3 cosas combinadas significan eso; para leer secuencialmente una matriz de enteros, es probable que la CPU obtenga previamente la siguiente línea de caché mientras realiza 16 lecturas de la línea de caché anterior; y cualquier costo de pérdida de caché no se notará y puede estar completamente oculto. Para prevenir esto; desearía acceder "aleatoriamente" a cada línea de caché una vez, para maximizar la diferencia de rendimiento medida entre "el conjunto de trabajo cabe en caché/s" y "el conjunto de trabajo no cabe en caché/s".

Finalmente, existen otros factores que pueden influir en las mediciones. Por ejemplo, para un sistema operativo que usa paginación (p. ej., Linux y casi todos los demás sistemas operativos modernos) hay una capa completa de almacenamiento en caché por encima de todo esto (TLB/Búferes de búsqueda de traducción), y TLB falla una vez que el conjunto de trabajo supera un cierto tamaño.; que debería ser visible como un cuarto "paso" en el gráfico. También hay interferencia del núcleo (IRQ, fallas de página, cambios de tareas, múltiples CPU, etc.); que podría ser visible como estática/error aleatorio en el gráfico (a menos que las pruebas se repitan con frecuencia y se descarten los valores atípicos). También hay artefactos del diseño de caché (asociación de caché) que pueden reducir la efectividad de la caché de maneras que dependen de las direcciones físicas asignadas por el núcleo; lo que podría verse como los "pasos" en el gráfico cambiando a diferentes lugares.


¿Hay algún problema con mi método?

Posiblemente, pero sin ver su código real que no se puede responder.

  • Su descripción de lo que está haciendo su código no dice si está leyendo la matriz una o varias veces.

  • Es posible que la matriz no sea lo suficientemente grande... dependiendo de su hardware. (¿No tienen algunos chips modernos un caché de tercer nivel de unos pocos megabytes?)

  • En el caso de Java en particular, debe hacer muchas cosas de la manera correcta para implementar un micro-benchmark significativo.

En el caso C:

  • Puede intentar ajustar los interruptores de optimización del compilador de C.

  • Dado que su código está accediendo a la matriz en serie, el compilador podría ordenar las instrucciones para que la CPU pueda mantenerse al día, o la CPU podría estar realizando una captación previa optimista o una captación amplia. Podría intentar leer los elementos de la matriz en un orden menos predecible.

  • Incluso es posible que el compilador haya optimizado completamente el ciclo porque el resultado del cálculo del ciclo no se usa para nada.

(Según estas preguntas y respuestas:¿Cuánto tiempo se tarda en recuperar una palabra de la memoria? Una recuperación de la memoria caché L2 es de ~7 nanosegundos y una recuperación de la memoria principal es de ~100 nanosegundos. Pero obtienes ~2 nanosegundos. Algo inteligente tiene que estar pasando aquí para que corra tan rápido como lo estás observando).


Linux
  1. Linux:¿cómo vaciar los búferes y la memoria caché en un sistema Linux?

  2. ¿Cómo instalar y configurar HAProxy en CentOS?

  3. Diferencia entre el montón de Java y el montón de C nativo

  4. ¿Cómo obtener mediante programación el tamaño de la página de caché de la CPU en C++?

  5. ¿Cómo deshabilitar las cachés L1 y L2 del procesador?

Cómo borrar (vaciar) la caché de DNS en Windows, MacOS y Linux

Cómo guardar un archivo en Vim/Vi y salir del editor

Cómo aumentar la memoria y la CPU en la máquina Vagrant

Cómo instalar Tomcat y Java en CentOS 8

Cómo configurar la ruta JAVA_HOME en Debian 11

¿En qué se parecen el tiempo de CPU y el uso de CPU?