Почему скорость memcpy () резко падает каждые 4 КБ?

Я проверил скоростьmemcpy() заметив, что скорость резко падает при i * 4KB. Результат выглядит следующим образом: ось Y - это скорость (МБ / с), а ось X - размер буфера дляmemcpy(), увеличиваясь с 1КБ до 2МБ. Подфигурка 2 и подфигурка 3 подробно описывают части 1КБ-150КБ и 1КБ-32КБ.

Среда:

Процессор: Intel (R) Xeon (R) CPU E5620 @ 2,40 ГГц

ОС: 2.6.35-22-generic # 33-Ubuntu

Флаги компилятора GCC: -O3 -msse4 -DINTEL_SSE4 -Wall -std = c99

Я думаю, это должно быть связано с кэшем, но я могуt найти причину из следующих кеш-недружественных случаев:

Почему моя программа работает медленно, когда зацикливается ровно на 8192 элемента?

Почему транспонирование матрицы 512x512 намного медленнее, чем транспонирование матрицы 513x513?

Поскольку снижение производительности в этих двух случаях вызвано недружественными циклами, которые считывают разбросанные байты в кэш, тратя впустую остальное пространство строки кэша.

Вот мой код:

void memcpy_speed(unsigned long buf_size, unsigned long iters){
    struct timeval start,  end;
    unsigned char * pbuff_1;
    unsigned char * pbuff_2;

    pbuff_1 = malloc(buf_size);
    pbuff_2 = malloc(buf_size);

    gettimeofday(&start, NULL);
    for(int i = 0; i < iters; ++i){
        memcpy(pbuff_2, pbuff_1, buf_size);
    }   
    gettimeofday(&end, NULL);
    printf("%5.3f\n", ((buf_size*iters)/(1.024*1.024))/((end.tv_sec - \
    start.tv_sec)*1000*1000+(end.tv_usec - start.tv_usec)));
    free(pbuff_1);
    free(pbuff_2);
}
ОБНОВИТЬ

Принимая во внимание предложения @usr, @ChrisW и @Leeor, я более точно переделал тест, и на графике ниже показаны результаты. Размер буфера составляет от 26 КБ до 38 КБ, и я тестировал его каждые остальные 64 ББ (26 КБ, 26 КБ + 64 Б, 26 КБ + 128 Б, ......, 38 КБ). Каждый тест повторяется 100 000 раз за 0,15 секунды. Интересно то, что падение происходит не только точно на границе 4 КБ, но и выходит в размере 4 * i + 2 КБ с гораздо меньшей амплитудой падения.

PS

@Leeor предложил способ заполнить каплю, добавив фиктивный буфер размером 2 КБ междуpbuff_1 а такжеpbuff_2, Это работает, но я не уверен насчет Лиораобъяснение.

Ответы на вопрос(3)

Ваш ответ на вопрос