Тест C / C ++ memcpu: измерение процессорного времени и времени простоя - PullRequest
0 голосов
/ 09 ноября 2019

Как можно тестировать memcpy? Я написал тестовый код, но он завершается немедленно (возможно, из-за оптимизации компилятора) и фактически не выделяет память:

void test(void)
{
 const uint32_t size = 4000'000'000;
 char a[size], b[size];
 printf("start\n");
 for(int i=0; i<10'000'000; i++)
     memcpy(b, a, size*sizeof(char));
 printf("end\n");
}// end of function

Я хочу знать стоимость memcpy в терминах процессорного времени ис точки зрения времени стены.

Вот ситуация: мне нужно обрабатывать входящие (через сеть) данные с высокой скоростью. Если я не обрабатываю его достаточно быстро, сетевые буферы переполняются, и я отсоединяюсь от источника данных (что часто встречается в моем тестовом коде). Я вижу, что загрузка процессора моим процессом довольно низкая (10-15%), и поэтому должна быть какая-то операция, которая стоит времени, не затрачивая время процессора. Итак, я хочу оценить вклад операций memcpy в время, необходимое для обработки одной единицы данных. Код в основном представляет собой некоторые вычисления и операции копирования в память: нет ресурса, который мне нужно ждать, который мог бы меня замедлить.

Спасибо за вашу помощь!

[РЕДАКТИРОВАТЬ:]

Большое спасибо за ваши комментарии! И извините за пример, который не является C (только C ++) - моим приоритетом была читаемость. Вот новый пример кода, который показывает, что memcpy не является бесплатным и потребляет 100% процессорного времени:

const uint32_t N = 1000'000'000;
char *a = new char[N], 
     *b = new char[N];
void test(void)
{
 for(uint32_t i=0; i<N; i++)
     a[i] = '7';

 printf("start\n");
 for(int i=0; i<100; i++)
     memcpy(b, a, N*sizeof(char));
 printf("end\n");
}// end of function

, что приводит меня в замешательство из-за того, что у меня низкая загрузка ЦП, но я не обрабатываю входящие данныедостаточно быстро.

1 Ответ

1 голос
/ 09 ноября 2019

Идея состояла в том, чтобы проверить, выполняется ли копирование памяти путем непосредственного копирования данных в ОЗУ с небольшим участием ЦП (что более вероятно, если вы увидите, что фрагменты ОЗУ велики, и поэтому в процессе не доминирует время ЦП).

Нет, memcpy на обычных компьютерах не выгружается на движок DMA / блистерная микросхема и позволяет процессору делать другие действия до тех пор, пока он не завершится. Копирование выполняется самим процессором, поэтому в отношении ОС memcpy ничем не отличается от любых других инструкций, которые может выполнять пользовательское пространство.

Реализация C ++ во встроенной системе или Atari MegaST может сделать это правдоподобно, позволяя ОС планировать другое задание или, по крайней мере, выполнять некоторые операции по домуХотя только с очень легким переключением контекста, потому что копирование даже огромного блока памяти занимает совсем немного времени.


Более простой способ выяснить это - сделать один шаг вmemcpy функция библиотеки. (И да, с вашим обновлением gcc не оптимизирует memcpy.)

Кроме того, тестирование memcpy 4 ГБ не очень характерно для сетевых пакетов. glibc memcpy на x86 использует другую стратегию (хранилища NT) для очень больших копий. И, например, пути read / recv ядра Linux в конечном итоге используют copy_to_user, который, как я полагаю, использует другую функцию копирования памяти: возможно rep movsb на процессорах x86 с функцией ERMSB.

См. Усовершенствованный REP MOVSB ​​для memcpy для получения подробной информации о производительности x86 памяти / кэша.

...