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

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

Ответ 1

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

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

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

Ответ 2

Я знаю, что этот поток немного устарел, но я хотел бы добавить дополнительную информацию. Во-первых, я согласен с тем, что QueryPerformanceCounter может занимать больше времени на определенных машинах, но я не уверен, что причиной этого является Рон. Хотя я занимался некоторыми исследованиями по этой проблеме, я нашел различные веб-страницы, в которых рассказывается о том, как QueryPerformanceCounter реализован. Например, Точность - это не то же самое, что и точность говорит мне, что Windows, HAL будет более конкретным, будет использовать другое устройство синхронизации для получения значения. Это означает, что если в окнах появится более медленное устройство синхронизации, такое как PIT, для получения значения времени потребуется больше времени. Очевидно, что использование PIT может потребовать транзакции PCI, поэтому это будет одна из причин.

Я также нашел еще одну статью: Как это работает: Вывод таймера в SQL Server 2008 R2 - Инвариантный TSC дает аналогичное описание. Фактически, в этой статье рассказывается, как SQLServer наилучшим образом выполнит транзакцию.

Затем я нашел дополнительную информацию о сайте VMware, потому что мне приходилось иметь дело с клиентами, которые используют виртуальные машины, и я обнаружил, что есть другие проблемы с измерением времени с виртуальными машинами. Для тех, кто интересуется, обратитесь к статье VMware - "Учет времени в виртуальных машинах VMware" В этой статье также говорится о том, как некоторые версии окон будут синхронизировать каждый TSC. Таким образом, было бы безопасно использовать QueryPerformanceCounter() в определенных ситуациях, и я думаю, что мы должны попробовать что-то вроде того, как это работает: выходы таймера в SQL Server 2008 R2 предложили найти, что может случиться, когда мы вызываем QueryPerformanceCounter()

Ответ 3

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

Ответ 4

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

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

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

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

Mike