Я протестировал скорость memcpy()
, заметив, что скорость резко падает при я * 4KB. Результат следующий: ось Y - это скорость (МБ/секунда), а ось Х - размер буфера для memcpy()
, увеличиваясь с 1 КБ до 2 МБ. На рисунках 2 и 3 представлены детали 1KB-150KB и 1KB-32KB.
Окружающая среда:
Процессор: Intel (R) Xeon (R) CPU E5620 @2,40 ГГц
ОС: 2.6.35-22-общий # 33-Ubuntu
Флаги компилятора GCC: -O3 -msse4 -DINTEL_SSE4 -Wall -std = c99
Я предполагаю, что это должно быть связано с кэшами, но я не могу найти причину из следующих небезопасных случаев, связанных с кешем:
-
Почему моя программа работает медленнее при циклировании по точно 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);
}
UPDATE
Учитывая предложения от @usr, @ChrisW и @Leeor, я уточнил тест более точно, и приведенный ниже график показывает результаты. Размер буфера составляет от 26 КБ до 38 КБ, и я тестировал его каждый другой 64B (26 КБ, 26 КБ + 64 Б, 26 КБ + 128 Б,......, 38 КБ). Каждый тест проходит 100 000 раз за 0.15 секунды. Интересно то, что падение происходит не только на границе 4 КБ, но и выходит в 4 * я + 2 КБ с гораздо меньшей амплитудой падения.
PS
@Leeor предложила способ заполнить капли, добавив 2-килобайтовый макет-буфер между pbuff_1
и pbuff_2
. Это работает, но я не уверен в объяснении Лиора.