2012-06-30 20 views
6

Estoy escribiendo un programa C en el que necesito enjuagar mi memoria. Me gustaría saber si hay algún comando del sistema UNIX para vaciar el caché de la CPU.¿Cómo vaciar el caché de CPU en Linux desde un programa C?

Este es un requisito para mi proyecto que implica calcular el tiempo necesario para mi lógica.

He leído acerca de la función cacheflush(char *s, int a, int b) pero no estoy seguro de si será adecuado y qué pasar en los parámetros.

+3

¿Por qué * * necesidad de vaciar la memoria caché? –

+0

es un requisito para mi proyecto que implica calcular el tiempo necesario para mi lógica, por lo tanto, necesito enjuagar el caché. –

+0

Posible duplicado de http://stackoverflow.com/questions/1756825/cpu-cache-flush – Tudor

Respuesta

6
  1. Debo entender que significa "caché de la CPU", no caché de memoria

  2. El enlace anterior es buena: la sugerencia de "escribir una gran cantidad de datos a través de la CPU" es no de Windows específica

  3. Aquí es otra variación sobre el mismo tema:

  4. He aquí un artículo sobre Linux y la memoria caché de la CPU:

NOTA:

En este (muy, muy bajo) nivel "Linux" ! = "Unix"

+0

Gracias por su ayuda. Es realmente una buena comunidad con gente servicial ... ¿puedes explicar cómo debo usar 'echo 3>/proc/sys/vm/drop_caches' en mi programa C con un pequeño código de ejemplo. –

+0

Una de las partes bellas de * nix (Unix en general y Linux específicamente) es que puedes tratar "todo como un archivo". Específicamente: 'fopen ("/proc/sys/vm/drop_caches "," w "); fprintf (fp, "3"); fclose (fp); '. PD: Si esta * es * tarea, use la etiqueta "tarea" en sus preguntas. – paulsm4

+0

Estoy usando fopen ("proc/sys/vm.drop_caches", "w") ... pero, ¿cómo puedo verificar que mi caché haya sido borrada? @ paulsm4 Gracias por ser amable y ayudar antes. Espero que ayudes esta vez también. :) –

2

Si está escribiendo un modo de usuario (no kernel-mode), y si tiene un único subproceso, entonces realmente no hay razón para que te molestes en enjuagar tu caché en primer lugar. Su programa en modo usuario puede olvidar que incluso existe; está ahí solo para acelerar la ejecución de su programa, y ​​el sistema operativo lo administra a través de la MMU del procesador.

Sólo hay un par de razones que se me ocurre que es posible que en realidad quieren vaciar la caché de su aplicación en modo de usuario:

  1. Su aplicación está destinada a funcionar en un sistema multiprocesador simétrico, o tiene transacciones de datos con hardware externo)
  2. Simplemente está probando su caché para algún tipo de prueba de rendimiento (en cuyo caso probablemente debería estar escribiendo su prueba para operar en modo kernel, quizás como un controlador).

En cualquier caso, asumiendo que usted está usando Linux ...

#include <asm/cachectl.h> 

int cacheflush(char *addr, int nbytes, int cache); 

Esto supone que tiene un bloque de memoria que acaba de escribir para y quiere asegurarse de que está purgada de la caché volver a la memoria principal. El bloque comienza a dir, y es nbytes larga, y está en una de las dos memorias caché (o ambos):

ICACHE Flush the instruction cache. 
    DCACHE Write back to memory and invalidate the affected valid cache lines. 
    BCACHE Same as (ICACHE|DCACHE). 

Lo normal sería sólo es necesario enjuagar el dcache, ya que al escribir datos en "memoria "(es decir, a la memoria caché), normalmente son datos, no instrucciones.

Si quiere vaciar "todo el caché" por algún extraño motivo de prueba, podría malloc() un gran bloque que sabe que es más grande que el caché de su CPU (¡dispare 8 veces más!), escribe cualquier basura vieja en ella, y simplemente tira todo ese bloque.

Consulte también: How to perform cache operations in C++?

+0

Gracias por ser tan útil. ¿Cómo puedo saber el tamaño de mi caché de CPU en ubuntu/unix/linux ... cuando quiero eliminar todo el caché –

+0

Ver http://superuser.com/questions/48505/how-to-find-virtual-memory -size-and-cache-size-of-a-linux-system Vea también mi segunda respuesta que creo que es más acorde a lo que está buscando ... Yo diría "más a lo largo de las líneas de lo que necesita ", salvo que creo que su objetivo de enjuagar el caché para las pruebas de rendimiento está equivocado. Lo que creo tendría más sentido para las pruebas de rendimiento sería probar el rendimiento de su código DESPUÉS de que se cargue en el caché, ejecutándolo una vez para ingresarlo en el caché, luego usar un temporizador para probarlo tal vez 10,000 veces y dividir el tiempo entre 10,000. – phonetagger

+0

'error: asm/cachectl.h: No existe tal archivo o directorio' el compilador gnu-gcc en Linux arroja este error. Alguna idea de cómo resolverlo ... de forma que acepte cachectl.h como un archivo de encabezado. –

1

bien, lo de mi primera respuesta. Más tarde, leí los comentarios de seguimiento debajo de su pregunta, así que me doy cuenta ahora que quiere descargar el INSTRUCTION CACHE para arrancar su programa (o partes de él) del caché, de modo que cuando pruebe su rendimiento, también pruebe su tiempo de carga inicial fuera de la memoria principal en la memoria caché de instrucciones. ¿También necesita vaciar todos los datos que su código utilizará en la memoria principal, de modo que tanto los datos como el código sean nuevas?

Antes que nada, me gustaría mencionar que la memoria principal también es una forma de caché, con su disco duro (el programa en el disco o el espacio de intercambio en el disco) siendo el más lento las instrucciones podrían venir de. Dicho esto, cuando se ejecuta por primera vez una rutina por primera vez, si todavía no se ha cargado en la memoria principal del disco por estar cerca de otro código que ya se ejecutó, primero se deben cargar las instrucciones de la CPU. del disco Eso lleva un orden de magnitud o más largo que cargarlo desde la memoria principal al caché. Luego, una vez que se carga en la memoria principal, se tarda un poco más de una orden de magnitud en cargar desde la memoria principal al caché de lo que lleva cargar desde el caché al buscador de instrucciones de la CPU. Entonces, si desea probar el rendimiento de arranque en frío de su código, debe decidir qué significa arranque en frío ... extraerlo del disco o extraerlo de la memoria principal. No conozco ningún comando para "vaciar" las instrucciones/datos de la memoria principal para intercambiar espacio, por lo que enjuagarlo en la memoria principal es todo lo que puede hacer (que yo sepa), pero tenga en cuenta que los resultados de su prueba aún pueden diferir de la primera ejecución (cuando puede arrancarlo del disco) en ejecuciones posteriores, incluso si vacía la caché de instrucciones.

Ahora, ¿cómo se puede vaciar el caché de instrucciones para asegurarse de que su propio código se vacíe en la memoria principal?

Si tuviera que hacer esto (algo muy raro de hacer en mi opinión), probablemente comenzaría por encontrar la longitud aproximada de & en la memoria de mis funciones. Como estoy usando Linux, emitiría el comando "objdump -d {myprogram}> myprogram.dump.txt", luego abriría myprogram.dump.txt en un editor y buscaría las funciones que quiero enjuagar y averiguar cuánto tiempo están restando su dirección de final de su dirección de inicio con una calculadora hexadecimal. Anotaría los tamaños de cada uno. Más tarde agregaría llamadas cacheflush() en mi código, dándole la dirección de cada función que quiero borrar como 'addr' y la longitud que encontré como 'nbytes', e ICACHE. Solo por seguridad probablemente me gustaría un poco de & agregar un 10% al tamaño, en caso de que haga algunos ajustes al código y olvide ajustar los nbytes. Haría una llamada a cacheflush() de esta manera para cada función que quiera eliminar. Luego, si necesito eliminar los datos también, si está usando datos globales/estáticos, también puedo eliminarlos (DCACHE), pero si se trata de datos de pila o montón, realmente no hay nada realista que pueda (o deba) hacer para enjuagar eso fuera de la memoria caché. Tratar de hacerlo sería un ejercicio de tontería, porque crearía una condición que nunca o muy raramente existiría en la ejecución normal. Suponiendo que está usando Linux ...

#include <asm/cachectl.h> 

int cacheflush(char *addr, int nbytes, int cache); 

...where cache is one of: 
    ICACHE Flush the instruction cache. 
    DCACHE Write back to memory and invalidate the affected valid cache lines. 
    BCACHE Same as (ICACHE|DCACHE). 

Por cierto, este es tarea para una clase?

+0

P: Esto solo es aplicable en modo kernel, ¿correcto? – paulsm4

+0

@ paulsm4 - La página man de Linux no dice nada al respecto. Hmmm. Leyendo la página del manual ... (supongo que está usando Linux, ¿verdad? ¿Intentó el comando "man cacheflush"?) ... cerca de la parte inferior, veo dos cosas en mi versión de la página del manual que son motivo de preocupación ... "ERRORES: la implementación actual ignora los argumentos addr y nbytes. Por lo tanto, toda la memoria caché siempre se vacía". Y más abajo ... "NOTA: esta llamada al sistema solo está disponible en sistemas basados ​​en MIPS. No debe usarse en programas destinados a ser portátiles." – phonetagger

+1

@ paulsm4 error: asm/cachectl.h: Ningún archivo o directorio el compilador gnu-gcc en Linux arroja este error. Alguna idea de cómo resolverlo ... de forma que acepte cachectl.h como un archivo de encabezado. –

1

Así es como Intel sugiere que vaciar la caché:

mem_flush(const void *p, unsigned int allocation_size){ 
    const size_t cache_line = 64; 
    const char *cp = (const char *)p; 
    size_t i = 0; 

    if (p == NULL || allocation_size <= 0) 
      return; 

    for (i = 0; i < allocation_size; i += cache_line) { 
      asm volatile("clflush (%0)\n\t" 
         : 
         : "r"(&cp[i]) 
         : "memory"); 
    } 

    asm volatile("sfence\n\t" 
       : 
       : 
       : "memory"); 
} 
+0

¿cuál es su fuente? – horro

Cuestiones relacionadas