Как точно измерить тактовые циклы, используемые функцией c ++?

Я знаю, что должен использовать: rdtsc. Измеренная функция детерминирована, но результат далек от воспроизводимого (я получаю 5% колебаний от цикла к запуску). Возможные причины:

  • переключение контекста
  • промахи в кеше

Вы знаете какие-нибудь другие причины? Как их устранить?


person Łukasz Lew    schedule 03.02.2009    source источник


Ответы (6)


TSC (то, что использует rdtsc) часто не синхронизируются в многопроцессорных системах. Это может помочь установить сродство ЦП, чтобы привязать процесс к одному ЦП.

Вы также можете получить временные метки из таймеров HPET, если они доступны, которые не подвержены той же проблеме. .

Что касается повторяемости, эти различия верны. Вы можете отключить кеширование, дать процессу приоритет в реальном времени и / или (если в Linux или что-то подобное) перекомпилировать ядро ​​с более низкой фиксированной частотой прерывания таймера (той, которая выполняет квантование времени). Вы не можете полностью устранить дисперсию, по крайней мере, нелегко и не в обычных комбинациях CPU + OS.

В общем, из соображений удобства программирования, надежности и переносимости я предлагаю вам использовать то, что предлагает ОС. Если он предлагает таймеры с высокой точностью, используйте соответствующий помощник ОС.

(На всякий случай, если вы пытаетесь провести атаку времени на криптосистему, что ж, вам придется жить с 1. этой случайностью и 2. общей защитой, которые делают систему непредсказуемой по уважительным причинам, поэтому функция может не работать. быть детерминированным по времени.)

РЕДАКТИРОВАТЬ: добавлен параграф о таймерах, которые может предложить ОС.

РЕДАКТИРОВАТЬ: это относится к Linux. Для привязки процесса к одному процессору (для точного чтения из RDTSC) вы можете использовать sched_setaffinity (2). И вот код одного из моих проектов, использующий его для других целей (отображение потоков на процессоры). Это должна быть ваша первая попытка. Что касается HPET, вы можете использовать обычные вызовы POSIX, например эти , если ядро ​​и машина поддерживают эти таймеры.

person Eduard - Gabriel Munteanu    schedule 03.02.2009
comment
Спасибо. Как привязать процесс к одному процессору? У вас есть какой-нибудь пример использования HPET? - person Łukasz Lew; 06.02.2009
comment
@ Лукаш Лью: В последнем абзаце разъяснены лучший подход и HPET. - person Eduard - Gabriel Munteanu; 07.02.2009

Зачем их устранять? Похоже, вы создали реалистичный тест. Этот код будет иметь такую ​​же изменчивость при использовании в дикой природе. Вероятно, хуже, так как вы, вероятно, устранили задержки диска и кеш-памяти ЦП. Использование подхода Джона Скита, создание условий, которые дадут вам наилучший результат, оставит вас только с результатом, который заставит вас чувствовать себя хорошо, но никогда не будет достижим.

Если важно абсолютное число, рассчитывайте медиану, а не среднее значение.

person Hans Passant    schedule 03.02.2009
comment
медиана кажется надежной. Но я не могу игнорировать случаи, когда тест длился вечно. - person Łukasz Lew; 06.02.2009

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

Хотя речь идет о Java, соображения применимы к тестированию производительности на любом языке.

См. Также: Как написать правильный микротест на Java?

Также см. Какой совет вы можете мне дать написать значимый тест?

person Lawrence Dol    schedule 03.02.2009

На самом деле в новых ядрах Linux есть новая подсистема perf. Пример:

$ ./perf stat du -s /tmp
94796   /tmp

 Performance counter stats for 'du -s /tmp':

          2.546403 task-clock-msecs         #      0.060 CPUs 
                 3 context-switches         #      0.001 M/sec
                 0 CPU-migrations           #      0.000 M/sec
               166 page-faults              #      0.065 M/sec
           2434963 cycles                   #    956.236 M/sec
           1798092 instructions             #      0.738 IPC  
            302969 branches                 #    118.979 M/sec
             26197 branch-misses            #      8.647 %    
             23217 cache-references         #      9.118 M/sec
              4621 cache-misses             #      1.815 M/sec

        0.042406580  seconds time elapsed
person Community    schedule 01.04.2011
comment
Можете ли вы предоставить ссылку или какой-либо источник? - person Łukasz Lew; 03.04.2011

Добавление к списку причин: предсказание ветвления / неверное предсказание (это может быть выполнено переключением контекста со сложными кешами предсказания на некоторых микросхемах. Также на предсказание могут влиять разные входные данные в вашу программу и, таким образом, прямое сравнение времени для двух разных данных наборы могут быть немного перекошены.

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

  • Промах в кэше: "Заправить" кэш перед началом отсчета времени. Не забывайте, что есть кэш инструкций, который также необходимо заполнить. Для небольших наборов данных просто запустите весь тест один раз без учета времени, а затем снова запустите его с указанием времени. Для больших наборов данных сделайте это, но затем используйте команду предварительного кэширования процессора, чтобы загрузить первый блок данных обратно в кэш.
  • Переключение контекста: используйте многопроцессорную / ядерную микросхему в слабо загруженной системе и установите привязку процесса к определенному процессору (желательно не CPU 0). Это также поможет с промахами в кеше (поскольку перемещение ЦП означает полную потерю кеша) и предсказанием ветвлений (поскольку на самом деле это форма кеша).

Но, конечно же, лучший метод определения времени, подобного этому, - это выполнять их очень много раз на очень больших фрагментах данных, чтобы свести к минимуму изменчивость, вносимую вещами, которые вы не можете контролировать. (На самом деле это невозможно стереть.)

person SoapBox    schedule 03.02.2009
comment
Если вы измеряете тактовые циклы, зачем вам исключать промахи в кэше и неверные предсказания переходов из вашего теста? Они также будут происходить в естественных условиях, поэтому важно просматривать все распределение, а не только оптимальный случай. - person Tom; 23.02.2009

Большинство современных процессоров поддерживают замечательный набор низкоуровневых аппаратных счетчиков производительности. Если вы действительно хотите знать ответы, включая реальные измерения промахов в кэше и накладных расходов на переключение контекста, возьмите PAPI (Performance API) toolkit, то в некоторых (хотя и не во всех) ОС установите один патч ядра, и, приложив некоторые дополнительные усилия, вы готовы к работе.

person Liudvikas Bukys    schedule 03.02.2009