Как получить количество циклов процессора в Win32?

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

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

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


Изменить: благодаря @Greg, который поместил меня на трек в QueryPerformanceCounter, который сделал трюк.

Ответ 1

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

Ответ 2

Вот интересная статья! говорит, что не использовать 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, и так on (вместо спящего с шагом до 10-15 мс).

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

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

Ответ 3

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

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

Ответ 4

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

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

Ответ 5

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