Я изучаю точные последствия использования QueryPerformanceCounter в нашей системе и пытаюсь понять его влияние на приложение. Я могу видеть, как запускать его на моем 4-ядерном процессоре с одним процессором, для его работы требуется около 230 нс. Когда я запускаю его на 24-ядерном 4-процессорном xeon, он занимает около 1,4 мс для запуска. Более интересно на моей машине при запуске в нескольких потоках они не влияют друг на друга. Но на машине с несколькими процессорами потоки вызывают какое-то взаимодействие, которое заставляет их блокировать друг друга. Мне интересно, есть ли общий ресурс на автобусе, который все они запрашивают? Что именно происходит, когда я вызываю QueryPerformanceCounter и что он действительно измеряет?Что происходит при вызове QueryPerformanceCounter?
ответ
Windows QueryPerformanceCounter() имеет логику для определения количества процессоров и при необходимости вызывает логику синхронизации. Он пытается использовать регистр TSC, но для многопроцессорных систем этот регистр не может быть синхронизирован между процессорами (и, что более важно, может сильно варьироваться из-за интеллектуальных состояний разгона и сна).
MSDN заявляет, что не имеет значения, на каком процессоре это вызвано, поэтому вы можете видеть дополнительный код синхронизации для такой ситуации, вызывающий накладные расходы. Также помните, что он может вызывать передачу по шине, чтобы вы могли наблюдать за задержками в конкуренции.
Попробуйте использовать SetThreadAffinityMask(), если возможно, привязать его к конкретному процессору. В противном случае вам просто придется жить с задержкой, или вы можете попробовать другой таймер (например, взгляните на http://en.wikipedia.org/wiki/High_Precision_Event_Timer).
У меня создалось впечатление, что на x86 QueryPerformanceCounter() просто называется rdtsc под обложками. Я удивлен, что у него есть замедление на многоядерных машинах (я никогда не замечал этого на своем 4-ядерном процессоре).
Я не знаю, что это значительное влияние на практике и, вероятно, не измеримо, если вы не смотрите прямо на него. На 4-ядерном процессоре все равно нет замедления :) –
rdtsc может сообщать о различных значениях для разных ядер и процессоров ... – Goz
@Goz, в то время как это было особенно актуально для старых Opterons, новые многоядерные процессоры имеют синхронизированные регистры TSC. –
Прошло много времени с тех пор, как я использовал это много, но если память служит, не существует одной реализации этой функции, так как кишки предоставляются различными производителями оборудования.
Вот небольшая статья из MSDN: http://msdn.microsoft.com/ja-jp/library/cc399059.aspx
Кроме того, если вы запрашиваете производительность на нескольких процессорах (в отличие от нескольких ядер на одном процессоре), это будет иметь, чтобы общаться через шину, который медленнее и может быть там, где вы видите некоторую блокировку.
Однако, как я уже говорил, это было довольно давно.
Майк
Я знаю, что эта нить немного старая, но я хотел бы добавить больше информации. Во-первых, я согласен с тем, что QueryPerformanceCounter может занимать больше времени на определенных машинах, но я не уверен, что причиной этого является ответ Рона. Хотя я занимался некоторыми исследованиями по этой проблеме, я нашел различные веб-страницы, в которых рассказывается о том, как QueryPerformanceCounter реализован. Например, Precision is not the same as accuracy сообщает мне, что Windows, HAL будет более конкретным, использовать другое устройство синхронизации для получения значения. Это означает, что если в окнах появится более медленное устройство синхронизации, такое как PIT, для получения значения времени потребуется больше времени. Очевидно, что использование PIT может потребовать транзакции PCI, поэтому это будет одна из причин.
Я также нашел другую статью: Как это работает: Выходы таймера в SQL Server 2008 R2 - Инвариантный TSC, дающий аналогичное описание. Фактически, в этой статье рассказывается, как SQLServer будет наилучшим образом выполнять транзакцию.
Затем я нашел дополнительную информацию о сайте VMware, потому что мне приходилось иметь дело с клиентами, которые используют виртуальные машины, и я обнаружил, что есть другие проблемы с измерением времени с помощью виртуальных машин. Для тех, кому это интересно, обратитесь к статье VMware - «Учет времени в виртуальных машинах VMware». В этой статье также рассказывается о том, как некоторые версии окон будут синхронизировать каждый TSC. Таким образом, было бы безопасно использовать QueryPerformanceCounter() в определенных ситуациях, и я думаю, что мы должны попробовать что-то вроде того, как это работает: выходы таймера в SQL Server 2008 R2 предложили найти, что может случиться, когда мы вызываем QueryPerformanceCounter()
- 1. Что происходит с потоками при вызове exec()?
- 2. Что происходит при вызове этого несуществующего конструктора?
- 3. Что происходит с EBP при вызове функции
- 4. Что происходит при вызове нового экземпляра объекта?
- 5. python Что происходит при вызове функции?
- 6. При использовании FileStream.WriteAsync(), что происходит при вызове метода снова
- 7. Что происходит, когда вы переключаете параметры при вызове функции calloc?
- 8. SQLAlchemy: Что происходит при вызове list() объекта Query?
- 9. Вызов процедуры Oracle с Java - что происходит при вызове System.exit()?
- 10. Что происходит на языке ассемблера при вызове метода/функции?
- 11. Что происходит при вызове Name.new? какой метод вызывается?
- 12. Что происходит при вызове функции блокировки от ISR в VxWorks
- 13. Что происходит с исходным массивом numpy при вызове функций OpenCV?
- 14. Что происходит с потоком кода при вызове AS3-прослушивателя?
- 15. Что действительно происходит при вызове метода асинхронного вызова?
- 16. Что именно происходит за кулисами при вызове System.gc()?
- 17. Что происходит при вызове метода async без ожидания?
- 18. Что происходит при вызове конструктора (понятная концепция в этом контексте)?
- 19. Что происходит при вызове Object.ToString, когда фактический тип является String
- 20. Что происходит в памяти при вызове функции с литеральными значениями?
- 21. Что происходит в стеке при вызове рекурсии с параметром?
- 22. Что на самом деле происходит при вызове Session.Abandon()?
- 23. Что происходит с динамической выделенной памятью при вызове execv()?
- 24. Ruby: получилось TypeError при вызове функции. Что происходит?
- 25. Что происходит с не ожидаемым асинхронным методом при вызове async?
- 26. Что происходит при вызове базовых функций из производных классов?
- 27. Что происходит при вызове str.erase с «pos», равным длине строки?
- 28. QueryPerformanceCounter при наличии фоновых процессов
- 29. Что происходит при обновлении?
- 30. Что происходит при вводе
omfg, 1.4 ** ms **! да, теперь это хороший вопрос. в соответствии с этим: http://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx он принимает 800 нс в качестве примера плохой машины. 1.4ms будет HYPER bad –
Я тоже укушен этим при написании профилировщика. Там таймер запрашивается каждый раз, когда функция запускается и возвращается. Использование QueryPerformanceCounter замедляет программу до обхода. Использование GetTickCount не вызывает заметного замедления, но оно непригодно для точного профилирования ... – Calmarius