Как измерить чтение / цикл или инструкции / цикл?

Я хочу тщательно измерить и настроить мой код C / C ++ для лучшей работы с кэшами в системе x86_64. Я знаю, как измерять время с помощью счетчика (QueryPerformanceCounter на моем компьютере с Windows), но мне интересно, как можно измерить инструкции за цикл или чтение / запись за цикл относительно рабочего набора.

Как я должен приступить к измерению этих значений?

1

Решение

Современные процессоры (то есть те, которые не очень ограничены, возраст которых менее 20 лет) являются суперскалярными, то есть они выполняют более одной инструкции за раз (при условии правильного порядка команд). Последние процессоры x86 переводят инструкции CISC во внутренние инструкции RISC, переупорядочивают их и выполняют результат, имеют даже несколько банков регистров, поэтому инструкции, использующие «одни и те же регистры», могут выполняться параллельно. Нет никакого разумного способа определить «время, которое занимает выполнение инструкции» сегодня.

Текущие процессоры много быстрее, чем память (несколько сотен команд — это типичная стоимость доступа к памяти), все они сильно зависят от производительности кеша. И затем у вас есть все виды забавных эффектов ядер, разделяющих (или нет) части кэша, …

Настройка кода для максимальной производительности начинается с архитектуры программного обеспечения, продолжается с организации программы, выбора алгоритма и структуры данных (здесь полезна также некоторая осведомленность о кеше / виртуальной памяти), тщательного программирования и (как наиболее крайних мер по выживанию последние 2% производительности) соображения, подобные тем, которые вы упомянули (и другой любимый, «переписать в сборке»). И порядок такой, потому что первые уровни дают больше производительности при тех же затратах. Мера прежде чем копаться, программисты общеизвестно ненадежный в поиске узких мест. И учитывайте стоимость реорганизации кода для повышения производительности, как в самой работе, так и в убеждении себя, что этот сложный код верен, и в обслуживании. Учитывая относительную стоимость компьютеров и людей, экстремальная настройка производительности редко имеет какой-либо смысл (возможно, для дорогостоящих путей кода в популярных операционных системах, в общих путях кода, генерируемых компилятором, но почти нигде в другом месте).

2

Другие решения

Если вас действительно интересует, где ваш код находится в кеше, а где — в памяти, а процессору меньше 10-15 лет, то в процессоре есть счетчики производительности. Вам нужно программное обеспечение уровня драйвера для доступа к этим регистрам, поэтому вы, вероятно, не хотите писать свои собственные инструменты для этого. К счастью, вам не нужно.

Есть такие инструменты, как VTune от Intel, CodeAnalyst от AMD и oprofile для Linux (работает как с процессорами AMD, так и с процессорами Intel).

Существует целый ряд различных регистров, которые подсчитывают количество фактически выполненных команд, количество циклов, которые ожидает процессор. Вы также можете получить количество таких вещей, как «количество чтений из памяти», «количество пропусков кэша», «количество пропусков TLB», «количество инструкций FPU».

Следующая, более сложная часть, конечно, состоит в том, чтобы попытаться решить любую из этих проблем, и, как уже упоминалось в другом ответе, программисты не всегда хорошо настраивают подобные вещи — и это, безусловно, отнимает много времени, не говоря уже о то, что хорошо работает на процессорной модели X, не обязательно будет работать быстро на модели Y (были некоторые приемы настройки для раннего Pentium 4, которые ОЧЕНЬ плохо работают на процессорах AMD — если, с другой стороны, вы настраиваете этот код для процессоров AMD того возраста , вы получите код, который хорошо работает на процессоре Intel того же поколения!)

1

Возможно, вас заинтересует инструкция rdtsc x86, которая читает относительное количество циклов.

Увидеть http://www.fftw.org/cycle.h для реализации читать счетчик во многих компиляторах.

Тем не менее, я бы предложил просто измерять с помощью QueryPerformanceCounter. Редко, чтобы фактическое количество циклов было важным, чтобы настроить код, вам, как правило, нужно только сравнить относительные измерения времени, и rdtsc имеет много подводных камней (хотя, вероятно, не применимо к описанной вами ситуации):

  • В многопроцессорных системах не существует единого значения счетчика когерентных циклов.
  • Современные процессоры часто регулируют частоту, изменяя скорость изменения во времени относительно скорости изменения в циклах.
0
По вопросам рекламы [email protected]