2009-08-12 11 views
15

Quiero leer una ubicación de memoria sin contaminar la memoria caché. Estoy trabajando en la máquina X86 Linux. He intentado utilizar la instrucción ensamblador MOVNTDQA:¿Cómo puedo cargar valores desde la memoria sin contaminar la caché?

asm("movntdqa %[source], %[dest] \n\t" 
     : [dest] "=x" (my_var) : [source] "m" (my_mem[0]) : "memory"); 

my_mem es un int * asignado con el nuevo, my_var es un int.

Tengo dos problemas con este enfoque:

  1. El código se compila, pero me estoy haciendo "instrucción ilegal" error al ejecutarlo. ¿Alguna idea de por qué?
  2. No estoy seguro de qué tipo de memoria se asigna con nueva. Yo asumiría que WB. De acuerdo con la documentación, la instrucción MOVNTDQA funcionará solo con el tipo de memoria USWC. ¿Cómo puedo saber en qué tipo de memoria estoy trabajando?

Para resumir, mi pregunta es:

¿Cómo puedo leer una posición de memoria sin contaminar el caché en un equipo x86? ¿Mi enfoque está en la dirección correcta y se puede arreglar para trabajar?

Gracias.

+0

¿Esta pregunta está relacionada? http: // stackoverflow.com/questions/851286/how-to-use-movntdqa-to-avoid-cache-pollution – sharptooth

+1

Supongo que está relacionado :), pero lamentablemente, esa pregunta/respuesta no me ayuda con esta pregunta. – Anna

+0

Oh, una cosa más: no estoy seguro de que sea posible hacerlo: -/Espero que así sea. – Anna

Respuesta

0

MOVNTDQA solo está disponible con SSE.

¿Por qué está tratando de evitar el uso de la memoria caché? Las CPU generalmente son bastante buenas para decidir qué expulsar de la memoria caché cuando. Si realmente lo necesita, una forma sería hacer que un alias del área de memoria desde la que está leyendo se asigne a su espacio de direcciones con el almacenamiento en caché desactivado y la lectura desde allí.

Si lo que intentas lograr es minimizar el impacto de tu código en el conjunto de trabajo de otra función que se mantiene en caché en ese momento, debería ser factible emitiendo las instrucciones apropiadas de captación previa e invalidación.

+0

Tengo dos núcleos en un proceso: uno de ellos usa mucho el caché y el otro tiene una prioridad más baja, por lo tanto, estoy tratando de disminuir su uso del caché. En esta máquina, la memoria caché L2 es mutua para los dos núcleos, por lo que me gustaría hacer que la memoria se cargue directamente en L1 o en los registros (en el programa de prioridad más baja). ¿Podrían explicarme cómo el uso de las instrucciones de captación previa e invalidación pueden ayudarme en este caso? Muchas gracias. – Anna

+0

Mi idea era organizar que el proceso de baja prioridad expulse explícitamente sus líneas de caché tan pronto como haya terminado con ellas, lo que permite que se rellenen antes de lo que la política de administración de caché de la CPU podría permitir, y tal vez arreglando el proceso de alta prioridad para emitir prefetches en secciones particularmente costosas. Sin embargo, no estoy seguro de cuánto ayudaría ese enfoque en su escenario. – moonshadow

+3

@moonshadow: Los procesadores no siempre son buenos para decidir qué almacenar en caché. Esa es la razón explícita de por qué hay una instrucción movntdqa. Es para transmisión de datos, una vez utilizado, nunca se volvió a tocar (al menos no demasiado pronto ;-)). En cuanto a un hilo de ayuda, esto podría ser viable, si hay otro hilo disponible, que no se puede utilizar por completo de lo contrario, viene a la mente hiper hilo. Pero en la mayoría de los casos obtendrá mejores resultados con dos hilos haciendo un trabajo completo y utilizando instrucciones explícitas de captación previa. – hirschhornsalz

7

El problema con la instrucción movntdqa con %% xmm como destino (carga desde la memoria) es que esta entrada solo está disponible con SSE4.1 y activado. Esto significa Core 2 (45 nm) o i7 más nuevos solo hasta ahora. A la inversa (almacenar datos en la memoria) está disponible en versiones anteriores de SSE.

Para esta instrucción, el procesador mueve los datos a uno muy pequeño de muy pocos búferes de lectura (Intel no especifica el tamaño exacto, pero supone que está en el rango de 16 bytes), donde está disponible, pero es expulsado después de algunas otras cargas.

Y no contamina las otras cachés, por lo que si tiene datos de transmisión, su enfoque es viable.

Recuerde, debe usar una entrada de seguridad después.

La recuperación previa existe en dos variantes: prefetcht0 (captura de datos en todas las memorias caché) y prefetchnt (captura de datos no temporales). Por lo general, la recuperación previa en todos los cachés es lo correcto, para un bucle de datos de transmisión, lo último sería mejor si utiliza las instrucciones de transmisión de forma continua.

Lo usa con la dirección de un objeto que desea usar en el futuro cercano, generalmente algunas iteraciones más adelante si tiene un bucle. La inserción previa no espera ni bloquea, solo hace que el procesador empiece a obtener los datos en la ubicación de memoria especificada.

Cuestiones relacionadas