Когда Intel впервые изобрела TSC, он измерил циклы процессора. Из-за различных возможностей управления питанием «циклы в секунду» не являются постоянными; поэтому TSC изначально был полезен для измерения производительности кода (и плохо для измерения пройденного времени).
Для лучшего или худшего; тогда у процессоров не было слишком много управления питанием, часто CPU работали с фиксированными «циклами в секунду» в любом случае. Некоторые программисты получили неправильную идею и неправильно использовали TSC для измерения времени, а не циклов. Позже (когда использование функций управления питанием стало более распространенным) эти люди злоупотребляли TSC, чтобы измерить время, скулящее по всем проблемам, вызванным их неправильным использованием. Производители процессоров (начиная с AMD) изменили TSC, поэтому он измеряет время, а не циклы (что делает его сломанным для измерения производительности кода, но верно для измерения пройденного времени). Это вызвало путаницу (программному обеспечению было сложно определить, что фактически измеряет TSC), поэтому немного позже AMD добавила флаг CPU TSC к CPUID, так что, если этот флаг установлен, программисты знают, что TSC сломан (для измерения циклов) или фиксированных (для измерения времени).
Intel последовала за AMD и изменила поведение своих TSC, чтобы также измерить время, а также приняла флаг AMD TSC Invariant.
Это дает 4 различных случая:
меры TSC как время, так и производительность (циклов в секунду постоянна)
меры TSC производительность не время
ТСК измеряет время и не но не использует флаг «TSC Invariant», чтобы сказать так
TSC меры ti я и не производительность и делает использование флага «ТСК» Инвариантным сказать так (самые современные процессоры)
В тех случаях, когда меры TSC времени, для измерения производительности/циклов правильно, вы должны использовать счетчики мониторинга производительности. К сожалению, счетчики контроля производительности различны для разных процессоров (для конкретной модели) и требуют доступа к MSR (привилегированный код). Это делает невозможным применение приложений для измерения «циклов».
Также обратите внимание, что если TSC измеряет время, вы не можете знать, какой временной масштаб он возвращает (сколько наносекунд в «притворном цикле»), не используя какой-либо другой источник времени для определения коэффициента масштабирования.
Вторая проблема заключается в том, что для многопроцессорных систем большинство операционных систем сосут. Правильный способ ОС для обработки TSC - запретить приложениям использовать его напрямую (установив флаг TSD
в CR4, чтобы команда RDTSC вызывала исключение). Это предотвращает различные уязвимости безопасности (временные побочные каналы). Он также позволяет ОС эмулировать TSC и гарантировать, что он вернет правильный результат. Например, когда приложение использует инструкцию RDTSC и вызывает исключение, обработчик исключений ОС может найти правильную «глобальную метку времени» для возврата.
Конечно, разные ЦП имеют свой собственный TSC. Это означает, что если приложение напрямую использует TSC, они получают разные значения для разных ЦП. Чтобы помочь людям справиться с неполадками ОС для устранения проблемы (путем эмуляции RDTSC, как и следовало ожидать); AMD добавила инструкцию RDTSCP
, которая возвращает TSC и «идентификатор процессора» (Intel закончила работу с инструкцией RDTSCP
). Приложение, работающее на сломанной ОС, может использовать «идентификатор процессора» для обнаружения, когда они работают на другом процессоре с последнего времени; и таким образом (используя команду RDTSCP
) они могут знать, когда «elapsed = TSC - previous_TSC» дает действительный результат. Однако; «Идентификатор процессора», возвращаемый этой инструкцией, является просто значением в MSR, и ОС должна установить это значение для каждого CPU на что-то другое, иначе RDTSCP
скажет, что «идентификатор процессора» равен нулю для всех процессоров.
В принципе; если процессоры поддерживают команду RDTSCP
, и если ОС правильно установила «идентификатор процессора» (используя MSR); то инструкция RDTSCP
может помочь приложениям узнать, когда у них получилось плохое «прошедшее время» (но это никак не связано с исправлением или недопущением плохих результатов).
So; коротко сократить длинную историю, если вы хотите получить точное измерение производительности, вы в основном завинчиваетесь. Лучшее, на что вы можете надеяться, это точное измерение времени; но только в некоторых случаях (например, при запуске на однопроцессорной машине или «закреплении» на конкретном процессоре или при использовании RDTSCP
на ОС, которые правильно настроили его, пока вы обнаруживаете и отбрасываете недопустимые значения).
Конечно, даже тогда вы получите изворотливые измерения из-за таких вещей, как IRQ.По этой причине; лучше всего запускать код много раз в цикле и отбрасывать любые результаты, которые намного выше других результатов.
Наконец, если вы действительно хотите сделать это правильно, вы должны измерить накладные расходы. Для этого вы бы определили, сколько времени потребуется, чтобы ничего не делать (только инструкция RDTSC/RDTSCP, в то же время отбрасывая изворотливые измерения); затем вычесть издержки измерения из результатов «измерения чего-то». Это дает вам более точную оценку времени, которое «что-то» на самом деле занимает.
Примечание. Если вы можете выкопать копию Руководства по системному программированию Intel от того, когда был выпущен Pentium (в середине 1990-х годов - не уверен, что он доступен в Интернете, я архивировал копии с 1980-х годов), вы обнаружите, что Intel документировала счетчик временных меток как нечто, что «может использоваться для мониторинга и идентификации относительного времени появления событий процессора». Они гарантировали, что (за исключением 64-битного обтекания) он будет монотонно увеличиваться (но не то, что он будет увеличиваться с фиксированной скоростью), и что он займет минимум 10 лет, прежде чем он обернется. Последняя редакция руководства документирует счетчик времени с более подробной информацией о том, что для более старых процессоров (P6, Pentium M, более старый Pentium 4) счетчик временных меток «увеличивается с каждым внутренним тактовым циклом процессора» и что «Intel (r) Переходы технологии SpeedStep (r) могут влиять на часы процессора »; и что более новые процессоры (более новый Pentium 4, Core Solo, Core Duo, Core 2, Atom) TSC увеличивается с постоянной скоростью (и что это «архитектурное поведение движется вперед»). По сути, с самого начала это был (переменный) «счетчик внутреннего цикла» для использования для отметки времени (а не счетчик времени, который будет использоваться для отслеживания времени «настенных часов»), и это поведение изменилось вскоре после 2000 год (на основе даты выпуска Pentium 4).
См http://stackoverflow.com/questions/3388134/rdtsc-accuracy-across-cpu-cores – nos
'__asm энергозависимой (" RDTSC ":" = A "(t));' является проблематичным (или неожиданным?) В GCC (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=21249). Ограничение '= A' означает' rax' в x86_64, а не 'edx: eax'. SHL 'rdx' by 32 и OR в' rax', или SHLD 'rdx' слева при смещении в битах' rax' справа. –