как использовать movntdqa, чтобы избежать загрязнения кеша?

Я пытаюсь написать функцию memcpy, которая не загружает исходную память в кеш процессора. Цель состоит в том, чтобы избежать загрязнения кеша. Приведенная ниже функция memcpy работает, но загрязняет кеш, как это делает стандартная функция memcpy. Я использую процессор P8700 с Visual C++ 2008 Express. я вижу использование кеша процессора с Intel vtune.

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;
    }
}

у меня есть другая версия, которая имеет те же результаты - работает, но загрязняет кеш.

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 


}
}

обновление: это тестовая программа

        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)
}

person yigal    schedule 12.05.2009    source источник
comment
Обратите внимание, что если вы действительно изучите несколько больших частей программного обеспечения, вы обнаружите, что большинство копий памяти на самом деле копируют менее 32 байтов, а копирование данных объемом более 4 КиБ почти никогда не происходит. Это означает, что оптимизация memcpy() для больших объемов данных (за счет накладных расходов при запуске, которые замедляют работу с небольшими копиями памяти) глупа, и ваша оптимизация просто ухудшает производительность реального программного обеспечения.   -  person Brendan    schedule 17.12.2012


Ответы (1)


Цитата из Интел:

«Инструкция потоковой загрузки предназначена для ускорения передачи данных из памяти типа USWC. Для других типов памяти, таких как кэшируемая (WB) или некэшируемая (UC), инструкция ведет себя как типичная 16-байтовая инструкция загрузки MOVDQA. Однако будущие процессоры может использовать инструкцию потоковой загрузки для других типов памяти (например, WB) как подсказку о том, что предполагаемая строка кэша должна быть передана из памяти непосредственно в ядро, сводя к минимуму загрязнение кэша».

Это объясняет, почему код не работает — память типа WB.

person yigal    schedule 12.05.2009
comment
Если вы довольны этим «решением» (т. е. MOVNTDQA не работает), не могли бы вы отметить это решение как принятое, чтобы другие люди сразу узнали об этом? - person dnadlinger; 15.02.2011