Подтвердить что ты не робот

Временные метки разрешения на микросекунду в Windows

Как получить временные метки разрешения в микросекундах в Windows?

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

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

Другим ресурсом является Получение точных временных меток в Windows XP, но для этого требуется несколько шагов, выполнение вспомогательной программы плюс некоторые элементы инициализации, Я не уверен, что он работает на нескольких процессорах.

Я также посмотрел статью Википедии Time Stamp Counter, которая интересна, но не так полезна.

Если ответ просто делает это с BSD или Linux, это намного проще и прекрасно, но я хотел бы подтвердить это и получить некоторое объяснение, почему это так сложно в Windows и так легко в Linux и BSD. Это то же самое прекрасное оборудование...

4b9b3361

Ответ 1

Я считаю, что это по-прежнему полезно: Внутренние системы: рекомендации по предоставлению поддержки мультимедийного таймера.

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

QueryPerformanceCounter не всегда будет работать со скоростью процессора. Фактически, он может попытаться избежать RDTSC, особенно в многопроцессорных (многоядерных) системах: он будет использовать HPET в Windows и Vista, а затем, если он доступен, или таймер ACPI/PM. В моей системе (Windows 7 x64, двухъядерный процессор AMD) таймер работает на частоте 14.31818 МГц.

То же самое верно для более ранних систем:

По умолчанию Windows Server 2003 с пакетом обновления 2 (SP2) использует таймер PM для всех многопроцессорных APIC или ACPI HAL, если процесс проверки не определяет, поддерживает ли BIOS поддержку APIC или ACPI HAL. "

Проблема в том, когда проверка завершилась неудачно. Это просто означает, что ваш компьютер /BIOS поврежден. Затем вы можете либо исправить свой BIOS (рекомендуется), либо, по крайней мере, переключиться на таймер ACPI (/usepmtimer) на данный момент.

Это легко из С# - без P/Invoke - чтобы проверить поддержку таймера с высоким разрешением с помощью Stopwatch.IsHighResolution, а затем загляните в Stopwatch.Frequency. Он сделает внутренний вызов QueryPerformanceCounter внутренним.

Также подумайте, что если таймеры будут разбиты, вся система будет опустошена и вообще будет вести себя странно, сообщать об отрицательном истекшем времени, замедлении и т.д. - не только ваше приложение.

Это означает, что вы действительно можете положиться на QueryPerformanceCounter.

... и вопреки распространенному мнению, QueryPerformanceFrequency() не может измениться во время работы системы.

Изменить: поскольку в документации на QueryPerformanceCounter() указано, что "не имеет значения, какой процессор вызывается" - и на самом деле все взлом с привязкой к потоку необходим только в случае сбоя обнаружения APIC/ACPI, и система прибегает к использованию TSC. Это курорт, который не должен произойти. Если это происходит в более старых системах, у производителя может возникнуть проблема с обновлением BIOS/драйвером. Если его нет, загрузочный переключатель /usepmtimer все еще существует. Если это не удастся, так как система не имеет надлежащего таймера, кроме Pentium TSC, вы можете на самом деле подумать о том, чтобы возиться с привязкой к потоку - даже тогда образец, предоставленный другими в области "Содержимое Сообщества" на странице, вводящий в заблуждение, поскольку у него есть незначительные накладные расходы из-за установки сродства нитей при каждом запуске/остановке вызова, что приводит к значительным задержкам и, вероятно, уменьшает преимущества использования таймера с высоким разрешением в первую очередь.

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

Я считаю, что сейчас довольно сложная задача - найти общий ПК с нулевой поддержкой ACPI и без использования таймера PM. Наиболее распространенным случаем является, вероятно, настройки BIOS, когда некорректная настройка ACPI (иногда, к сожалению, по умолчанию factory).

Анекдоты рассказывают, что восемь лет назад ситуация была иной в редких случаях. (Делает забавное чтение, разработчики работают над дизайном "недостатки" и избивают дизайнеров чипов. Если быть справедливым, то это может быть наоборот: -)

Ответ 2

QueryPerformanceCounter/QueryPerformanceFrequency, разрешение скорости процессора

Просто будьте осторожны с многопоточными. Каждое ядро ​​на процессоре может иметь свой собственный счетчик.

Дополнительная информация находится в Получение точных временных меток в Windows XP.

Если вам придётся использовать этот метод:

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

Ответ 3

  • Windows не является операционной системой реального времени.

  • Процессы в многозадачной ОС должны будут дать свое время другому потоку/процессу. Это дает некоторые накладные расходы на время.

  • Каждый вызов функции будет иметь накладные расходы, что дает небольшую задержку при возврате запроса.

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

  • Некоторые операционные системы, такие как Linux или BSD, но они все равно не могут поддерживать точное временное разрешение субмикросекунды (например, точность nanosleep() в Linux составляет около 1 мкс, не менее 1 мкс), за исключением того, что вы меняете ядро ​​на какой-то конкретный планировщик, который приносит пользу вашим приложениям.

Итак, я думаю, лучше адаптировать приложение, чтобы следить за этими проблемами, например, часто повторяя частоту вашей синхронизации, и это то, что предоставляют ваши ссылки. AFAIK, самое высокое разрешение по таймеру для Windows по-прежнему является GetPerformanceCounter/Frequency() независимо от его точности. Вы можете получить лучшую точность, запустив рутинную процедуру таймера в отдельном потоке и настроив привязку потока к одному из основных процессоров и установите приоритет потока как можно более высокий.

Ответ 4

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

См. QueryPerformanceCounter

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

Ответ 5

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

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

Ответ 6

В ответах пока есть много хорошей информации.

Если то, что вы ищете, - это простой способ получить истекшее время с 1 января 1970 года в миллисекундах или более высоком разрешении в Windows XP или более поздней версии, там очень простой кросс-платформенный пример этого в CurrentTime.cpp выпуска Apple OSS для JavaScriptCore для MacOS 10.7.5 (я не могу найти его в своих версиях 10.8+). Код, о котором я говорю, находится в функции CurrentTime().

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

В нем не учитываются переключатели контекста, которые немного отбрасывают вещи (в качестве "Внедрить постоянное обновление, поставщик времени с высоким разрешением для Windows" и "Проект Timestamp Windows" , но он постоянно пересинхронизируется. Я бы не запускал с ним ракеты, но примерно в 50 строках кода это было просто реализовать и достаточно хорошо для многих целей.

Кроме того, если вы знаете, что вам гарантированно будет работать Windows 8/Windows Server 2012, вы должны просто использовать GetSystemTimePreciseAsFileTime(), поскольку он возвращает системную дату и время с максимально возможной точностью (1 микросекунда или лучше).

Ответ 7

Я использовал класс DateTimePrecise из Проект кода.

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

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

Удачи...

Ответ 8

Я обнаружил трудности с использованием PerformanceCounter вместе с PerformanceCounterFrequency, потому что данный PerformanceCounterFrequency отклоняется от фактической частоты.

Он отклоняется на смещение, а также показывает тепловой дрейф. Более новое оборудование, похоже, имеет меньший дрейф, но смещение и смещение довольно значительны. Дрейф в несколько миллионных долей будет в значительной степени повредить точность микросекунды, так как 1 ppm составляет 1 мкс/с! Поэтому рекомендуется тщательная аппаратная калибровка при использовании PerformanceCounter с PerformanceCounterFrequency. Это также может быть причиной того, что "безумные результаты" наблюдаются, когда часто не вызываются определенные функции.

Я сделал несколько более подробных исследований по этому вопросу. Описание можно найти в службе разрешения времени Microsecond для Windows.