Что происходит при вызове QueryPerformanceCounter?

Я изучаю точные последствия использования QueryPerformanceCounter в нашей системе и пытаюсь понять его влияние на приложение. Я вижу, запустив его на своем 4-ядерном компьютере с одним процессором, что для его работы требуется около 230 нс. Когда я запускаю его на 24-ядерном 4 процессоре xeon, он запускается примерно за 1,4 мс. Что еще интереснее, на моей машине при запуске в нескольких потоках они не влияют друг на друга. Но на машине с несколькими процессорами потоки вызывают какое-то взаимодействие, которое заставляет их блокировать друг друга. Мне интересно, есть ли на шине какой-то общий ресурс, который они все запрашивают? Что именно происходит, когда я вызываю QueryPerformanceCounter, и что он на самом деле измеряет?


person Matt Price    schedule 12.11.2009    source источник
comment
omfg, 1,4 мс! да, теперь это хороший вопрос. согласно здесь: msdn.microsoft .com / en-us / library / windows / desktop / требуется 800 нс в качестве примера плохо работающей машины. 1,4 мс было бы HYPER плохо   -  person v.oddou    schedule 30.07.2014
comment
Меня это тоже укусило при написании профилировщика. Там таймер опрашивается каждый раз, когда функция запускается и возвращается. Использование QueryPerformanceCounter замедляет сканирование программы. Использование GetTickCount не вызывает заметного замедления, но его нельзя использовать для точного профилирования ...   -  person Calmarius    schedule 31.12.2014


Ответы (4)


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

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

Попробуйте использовать SetThreadAffinityMask (), если возможно, привязать его к определенному процессору. В противном случае вам, возможно, придется жить с задержкой или вы можете попробовать другой таймер (например, посмотрите http://en.wikipedia.org/wiki/High_Precision_Event_Timer).

person Ron Warholic    schedule 12.11.2009

Я знаю, что эта ветка устарела, но я хотел бы добавить больше информации. Во-первых, я согласен с тем, что 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 ()

person istudy0    schedule 03.09.2010

У меня создалось впечатление, что на x86 QueryPerformanceCounter () просто вызывал rdtsc под прикрытием. Я удивлен, что у него есть замедление на многоядерных машинах (я никогда не замечал этого на моем 4-ядерном процессоре).

person Aaron    schedule 12.11.2009
comment
Я не знаю, оказывает ли это существенное влияние на практике и, вероятно, не поддается измерению, если вы не ищете его напрямую. На 4-ядерном процессоре все равно вообще нет подтормаживания :) - person Matt Price; 12.11.2009
comment
@Goz, хотя это было особенно верно для старых Opteron, новые многоядерные процессоры синхронизировали регистры TSC. - person v.oddou; 01.09.2014
comment
@ v.oddou: Возможно, правда ... но разве счетчик временных меток не является простым подсчетом циклов? Учитывает ли троттлинг? - person Goz; 01.09.2014
comment
@Goz да, я много думал об этой проблеме. Единственное, что я могу разумно представить, это то, что происходит на практике, - это то, что все ядра масштабируют скорость вместе. Это отражено в таких программах, как coretemp или CPUz, которые отображают только 1 частоту, но 4 температуры и полосы использования. - person v.oddou; 01.09.2014

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

Вот небольшая статья из MSDN: http://msdn.microsoft.com/ja-jp/library/cc399059.aspx

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

Однако, как я уже сказал, прошло довольно много времени.

Майк

person mkgrunder    schedule 12.11.2009