Как получить количество циклов ЦП в Win32? - PullRequest
7 голосов
/ 26 сентября 2008

В Win32 есть ли способ получить уникальное число циклов ЦП или что-то подобное, что было бы одинаково для нескольких процессов / языков / систем / и т. Д.

Я создаю несколько файлов журналов, но мне нужно создать несколько файлов журналов, потому что мы храним среду выполнения .NET, и я бы хотел избежать звонков от одного к другому для входа. Таким образом, я думал, что просто создам два файла, объединю их, а затем отсортирую их, чтобы получить согласованную временную шкалу, включающую вызовы между мирами.

Однако GetTickCount не увеличивается для каждого вызова, так что это ненадежно. Есть ли лучший номер, чтобы при сортировке я получал звонки в правильном порядке?


Редактировать : Благодаря @ Greg , который поставил меня на путь к QueryPerformanceCounter, который добился цели.

Ответы [ 5 ]

12 голосов
/ 26 сентября 2008

Вот интересная статья! говорит, что не следует использовать RDTSC, а вместо этого использовать QueryPerformanceCounter .

Вывод:

Используя обычный старый timeGetTime(), чтобы сделать сроки не надежны на многих Операционные системы на базе Windows потому что гранулярность системы таймер может достигать 10-15 миллисекунды, что означает, что timeGetTime() только с точностью до 10-15 миллисекунд. [Обратите внимание, что высокая зернистость наблюдается на основе NT операционные системы, такие как Windows NT, 2000 и XP. Windows 95 и 98 склонны иметь гораздо лучшую зернистость, около 1-5 мс.]

Однако, если вы позвоните timeBeginPeriod(1) в начале ваша программа (и timeEndPeriod(1) в конец), timeGetTime() будет обычно с точностью до 1-2 миллисекунд, и предоставит вам чрезвычайно точная информация о времени.

Sleep() ведет себя аналогично; длина времени, которое на самом деле Sleep() спит идет рука об руку с зернистость timeGetTime(), поэтому после позвонив timeBeginPeriod(1) один раз, Sleep(1) будет на самом деле спать 1-2 миллисекунды, Sleep(2) на 2-3, и так на (вместо того, чтобы спать в приращениях 10-15 мс).

Для более точной синхронизации (с точностью до миллисекунды), вы будете вероятно, хотите избежать использования Мнемоническая сборка RDTSC, потому что это трудно калибровать ; вместо этого используйте QueryPerformanceFrequency и QueryPerformanceCounter, которые с точностью до 10 микросекунд (0,00001 секунды).

Для простой синхронизации оба timeGetTime и QueryPerformanceCounter работают хорошо, и QueryPerformanceCounter - это очевидно точнее. Однако если вам нужно сделать любой вид паузы "(такие, которые необходимы для ограничение частоты кадров), вы должны быть осторожно сидеть в цикле вызова QueryPerformanceCounter, ожидая это достичь определенной ценности; это будет съешь 100% своего процессора. Вместо этого рассмотрим гибридную схему, где вы звоните Sleep (1) (не забудьте timeBeginPeriod (1) first!) всякий раз, когда вам нужно пройти более 1 мс время, а затем только введите QueryPerformanceCounter 100% - занятая петля прикончить последнюю <1/1000-ую вторая задержка вам нужна. это даст вам сверхточные задержки (с точностью до 10 микросекунд), с очень минимальное использование процессора. См код выше. </p>

8 голосов
/ 26 сентября 2008

Вы можете использовать инструкцию процессора RDTSC (при условии x86). Эта инструкция дает счетчик циклов ЦП, но имейте в виду, что он очень быстро увеличится до своего максимального значения, а затем сбросится до 0. Как упоминается в статье в Википедии, вам может быть лучше использовать функцию QueryPerformanceCounter .

2 голосов
/ 26 сентября 2008

Выход RDTSC может зависеть от тактовой частоты текущего ядра, которая для современных процессоров не является ни постоянной, ни, на многоядерной машине, непротиворечивой.

Используйте системное время, а при работе с фидами из нескольких систем используйте источник времени NTP. Таким образом, вы можете получать надежные и стабильные показания времени; если накладные расходы слишком велики для ваших целей, используйте HPET , чтобы отработать время, прошедшее с момента последнего известного считывания надежного времени, лучше, чем использование только HPET.

2 голосов
/ 26 сентября 2008

System.Diagnostics.Stopwatch.GetTimestamp () возвращает номер цикла ЦП с момента возникновения времени (может быть, когда компьютер запускается, но я не уверен), и я никогда не видел, чтобы он не увеличивался между 2 вызовами.

Циклы ЦП будут характерны для каждого компьютера, поэтому вы не можете использовать его для объединения файлов журнала между двумя компьютерами.

1 голос
/ 26 сентября 2008

Используйте GetTickCount и добавьте еще один счетчик при объединении файлов журнала. Не даст вам идеальной последовательности между различными файлами журналов, но он, по крайней мере, сохранит все журналы каждого файла в правильном порядке.

...