2009-05-12 7 views
11

Estoy tratando de escribir una función memcpy que no cargue la memoria fuente a la memoria caché de la CPU. El propósito es evitar la contaminación del escondite. La función memcpy a continuación funciona, pero contamina la memoria caché como lo hace la memcpy estándar. Estoy usando el proccesoor P8700 con visual C++ 2008 express. veo el uso de la memoria caché de la CPU con intel vtune.cómo usar movntdqa para evitar la contaminación del caché?

void memcpy(char *dst,char*src,unsigned size){ 
    char *dst_end=dst+size; 
    while(dst!=dst_end){ 
     __m128i res = _mm_stream_load_si128((__m128i *)src); 
     *((__m128i *)dst)=res; 
     src+=16; 
     dst+=16; 
    } 
} 

tengo otra versión, que tiene los mismos resultados - funciona pero contamina la caché.

void memcpy(char *dst,char*src,unsigned size){ 

     char *dst_end = dst+size; 

     __asm{ 
     mov edi, dst 
     mov edx, dst_end 
     mov esi,src 
     inner_start: 
     LFENCE 
     MOVNTDQA xmm0, [esi ] 
     MOVNTDQA xmm1, [esi+16] 
     MOVNTDQA xmm2, [esi+32] 
     MOVNTDQA xmm3, [esi+48] 
     //19. ; Copy data to buffer 
     MOVDQA [edi], xmm0 
     MOVDQA [edi+16], xmm1 
     MOVDQA [edi+32], xmm2 
     MOVDQA [edi+48], xmm3 
    // 25. ; Increment pointers by cache line size and test for end of loop 
     add esi, 040h 
     add edi, 040h 
     cmp edi, edx 
     jne inner_start 


} 
} 

actualización: este es el programa de pruebas

 void test(int table_size,int num_iter,int item_size){ 
      char *src_table=alloc_aligned(table_size*item_size);//return value is aligned on 64 bytes 
      char *dst=alloc_aligned(item_size); //destination is always the same buffer 
      for (int i=0;i<num_iter;i++){ 
       int location=my_rand()%table_size; 
       char *src=src_table+location*item_size;//selecting a different src every time 
       memcpy(dst,src,item_size); 
      } 

     } 
main(){ 
     test(1024*32,1024*1024,1024*32) 
} 
+1

Tenga en cuenta que si realmente estudiar varias grandes piezas de software, usted encontrará que la mayoría de las copias de memoria en realidad copia de menos de 32 bytes y Copiar más de 4 KiB de datos casi nunca sucede. Lo que esto significa es que optimizo 'me mcpy() 'para grandes cantidades de datos (a expensas de la sobrecarga de inicio que hace que sea más lento para pequeñas copias de memoria) es una tontería y su optimización solo empeora el rendimiento para el software del mundo real. – Brendan

Respuesta

8

Citando Intel:

"La instrucción de carga streaming es cuyo objetivo es acelerar la transferencia de datos desde el tipo de memoria USWC. Para otros tipos de memoria como cacheable (WB) o Uncacheable (UC), la instrucción se comporta como una instrucción de carga MOVDQA de 16 bytes típica. Sin embargo, los futuros procesadores pueden utilizar la transmisión de carga instrucción para otros tipos de memoria (como el Banco Mundial) como un indicio de que la línea de caché destinada debería ser escuchados de la memoria directamente al núcleo, mientras que minimizar la contaminación de caché."

eso explica por qué el código no funciona -. la memoria es de tipo BM

+0

Si está contento con esta »solución« (es decir, MOVNTDQA no funciona), ¿podría marcar esta solución como aceptada para que otras personas lo sepan de un vistazo? – klickverbot

Cuestiones relacionadas