Я изучаю точные последствия использования QueryPerformanceCounter в нашей системе и пытаюсь понять его влияние на приложение. Я вижу, запустив его на своем 4-ядерном компьютере с одним процессором, что для его работы требуется около 230 нс. Когда я запускаю его на 24-ядерном 4 процессоре xeon, он запускается примерно за 1,4 мс. Что еще интереснее, на моей машине при запуске в нескольких потоках они не влияют друг на друга. Но на машине с несколькими процессорами потоки вызывают какое-то взаимодействие, которое заставляет их блокировать друг друга. Мне интересно, есть ли на шине какой-то общий ресурс, который они все запрашивают? Что именно происходит, когда я вызываю QueryPerformanceCounter, и что он на самом деле измеряет?
Что происходит при вызове QueryPerformanceCounter?
Ответы (4)
Windows QueryPerformanceCounter () имеет логику для определения количества процессоров и вызова логики синхронизации при необходимости. Он пытается использовать регистр TSC, но для многопроцессорных систем не гарантируется, что этот регистр будет синхронизироваться между процессорами (и, что более важно, он может сильно различаться из-за интеллектуального понижения частоты и состояний сна).
MSDN говорит, что не имеет значения, на каком процессоре это вызвано, поэтому вы можете увидеть дополнительный код синхронизации для такой ситуации, вызывающий накладные расходы. Также помните, что он может вызывать передачу по шине, поэтому вы можете видеть задержки из-за конкуренции на шине.
Попробуйте использовать SetThreadAffinityMask (), если возможно, привязать его к определенному процессору. В противном случае вам, возможно, придется жить с задержкой или вы можете попробовать другой таймер (например, посмотрите http://en.wikipedia.org/wiki/High_Precision_Event_Timer).
Я знаю, что эта ветка устарела, но я хотел бы добавить больше информации. Во-первых, я согласен с тем, что QueryPerformanceCounter может занимать больше времени на определенных машинах, но я не уверен, что ответ Рона все время является причиной этого. Пока я исследовал эту проблему, я нашел несколько веб-страниц, на которых рассказывается о том, как реализован QueryPerformanceCounter. Например, Точность - это не то же самое, что точность сообщает мне, что Windows, а точнее HAL, будет использовать другое устройство синхронизации для получения значения. Это означает, что если Windows будет использовать более медленное устройство синхронизации, такое как PIT, для получения значения времени потребуется больше времени. Очевидно, что для использования PIT может потребоваться транзакция PCI, поэтому это может быть одной из причин.
Я также нашел другую статью: Как это работает: выходы таймера в SQL Server 2008 R2 - неизменный TSC, дающий аналогичное описание. Фактически, в этой статье рассказывается, как SQLServer наилучшим образом синхронизирует транзакцию.
Затем я нашел дополнительную информацию на сайте VMware, потому что мне приходилось иметь дело с клиентами, которые используют виртуальные машины, и я обнаружил, что есть и другие проблемы с измерением времени с помощью виртуальных машин. Для тех, кому интересно, пожалуйста, обратитесь к документу VMware - Учет времени в виртуальных машинах VMware. В этом документе также рассказывается о том, как некоторые версии Windows будут синхронизировать каждый TSC. Таким образом, было бы безопасно использовать QueryPerformanceCounter () в определенных ситуациях, и я думаю, что мы должны попробовать что-то вроде того, что предлагает How It Works: Timer Outputs в SQL Server 2008 R2, чтобы найти, что может произойти, когда мы вызываем QueryPerformanceCounter ()
У меня создалось впечатление, что на x86 QueryPerformanceCounter () просто вызывал rdtsc под прикрытием. Я удивлен, что у него есть замедление на многоядерных машинах (я никогда не замечал этого на моем 4-ядерном процессоре).
Прошло много времени с тех пор, как я использовал это много, но если память не изменяет, нет ни одной реализации этой функции, поскольку внутренности предоставляются различными производителями оборудования.
Вот небольшая статья из MSDN: http://msdn.microsoft.com/ja-jp/library/cc399059.aspx
Кроме того, если вы запрашиваете производительность нескольких процессоров (в отличие от нескольких ядер на одном процессоре), ему придется взаимодействовать через шину, что и медленнее, и может быть там, где вы видите некоторую блокировку.
Однако, как я уже сказал, прошло довольно много времени.
Майк
QueryPerformanceCounter
замедляет сканирование программы. ИспользованиеGetTickCount
не вызывает заметного замедления, но его нельзя использовать для точного профилирования ... - person Calmarius   schedule 31.12.2014