Как рассчитать время операции с точностью до микросекунды - PullRequest
6 голосов
/ 13 мая 2010

Я хочу рассчитать производительность функции с точностью до микросекунды на платформе Windows.

Теперь сама Windows обладает миллисекундной гранулярностью, так как мне этого добиться.

Я пробовал следующий пример, но не получил правильных результатов.

LARGE_INTEGER ticksPerSecond = {0};
LARGE_INTEGER tick_1 = {0};
LARGE_INTEGER tick_2 = {0};
double uSec = 1000000;

// Get the frequency
QueryPerformanceFrequency(&ticksPerSecond);

//Calculate per uSec freq
double uFreq = ticksPerSecond.QuadPart/uSec;

// Get counter b4 start of op
QueryPerformanceCounter(&tick_1);

// The ope itself
Sleep(10);

// Get counter after opfinished
QueryPerformanceCounter(&tick_2);

// And now the op time in uSec
double diff = (tick_2.QuadPart/uFreq) - (tick_1.QuadPart/uFreq);

Ответы [ 8 ]

20 голосов
/ 13 мая 2010

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

7 голосов
/ 13 мая 2010
  • скомпилируйте
  • посмотрите на вывод ассемблера
  • подсчитать количество каждой инструкции в вашей функции
  • применить циклы на инструкцию к целевому процессору
  • заканчивается счетом циклов
  • умножьте на тактовую частоту
  • применять произвольные коэффициенты масштабирования для учета ошибок кэша и неправильных прогнозов ветвлений. Lol

(мужик, за которого я так проголосую за этот ответ)

3 голосов
/ 13 мая 2010

Нет, вы, вероятно, получаете точный результат, QueryPerformanceCounter () хорошо работает для временных интервалов. Что не так, так это ваше ожидание точности Sleep (). Он имеет разрешение 1 миллисекунду, его точность намного хуже. Не лучше, чем примерно 15.625 миллисекунд на большинстве компьютеров с Windows.

Чтобы получить значение, близкое к 1 миллисекунде, сначала нужно вызвать timeBeginPeriod (1) . Это, вероятно, улучшит соответствие, игнорируя дрожание, которое вы получите от Windows, являющейся многозадачной операционной системой.

0 голосов
/ 18 июля 2010

Санджит,

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

Я хочу вернуться к исходному вопросу о том, как измерять время в окнах с точностью до микросекунды. Как вы уже знаете, высокопроизводительный счетчик (то есть QueryPerformanceCounter) «тикает» с частотой, сообщаемой QueryPerformanceFrequency. Это означает, что вы можете измерять время с точностью, равной:

1 / частота секунд

На моей машине QueryPerformanceFrequency сообщает 2337910 (счетчиков в секунду). Это означает, что QPC моего компьютера может измерять с точностью 4,277e-7 секунд или 0,427732 мкс. Это означает, что наименьший бит времени, который я могу измерить, составляет 0,427732 мкс. Это, конечно, дает вам точность, о которой вы изначально просили :) Частота вашей машины должна быть схожей, но вы всегда можете выполнить математику и проверить ее.

0 голосов
/ 14 мая 2010

Мне нравится ответ Матти Вирккунен. Проверьте время, вызовите функцию большое количество раз, проверьте время, когда вы закончите, и разделите на количество раз, которое вы вызвали функцию. Он упомянул, что вы можете отключиться из-за прерываний ОС Вы можете изменить количество звонков и увидеть разницу. Можете ли вы повысить приоритет процесса? Можете ли вы получить все вызовы в пределах одного временного интервала ОС?

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

0 голосов
/ 14 мая 2010

Или вы можете использовать gettimeofday (), которая дает вам временную структуру, которая является временной меткой (вплоть до мкс)

0 голосов
/ 13 мая 2010

Чтобы получить более точное разрешение, чем 1 мс, вам придется обратиться к документации по вашей ОС. Могут быть API для получения разрешения таймера в микросекундном разрешении. Если это так, запустите ваше приложение много раз и возьмите средние значения.

0 голосов
/ 13 мая 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...