- Rdtsc
-
rdtsc (англ. Read Time Stamp Counter) — ассемблерная инструкция для платформы x86, читающая счётчик TSC (Time Stamp Counter) и возвращающая его в регистрах EDX:EAX 64-битное количество тактов с момента последнего сброса процессора.
rdtsc поддерживается в процессорах Pentium (и совместимых с ними) и более новых. Опкод: 0F 31.
rdtscp[1] поддерживается начиная с Intel Nehalem и AMD Family 0x0F[2]. Опкод: 0F 01 F9.[3]
Содержание
Использование
rdtsc чаще всего используется:
- для измерения времени;
- для точного измерения временных интервалов;
- при оптимизации — для измерения времени, необходимого для выполнения конкретных инструкций или их набора;
- в антиотладочных целях;[4][5]
- как источник энтропии для генераторов псевдослучайных чисел.[6]
Преимущества
В сравнении с предоставляемыми операционными системами API (при условии отсутствия перечисленных ниже проблем) вроде WINAPI::QueryPerformanceCounter() или gettimeofday() инструкция rdtsc предоставляет следующие преимущества.
- Точность почти до тика, что особенно критично для архитектур и операционных систем, полноценно не поддерживающих HPET, то есть всех сколько-нибудь устаревших ПК и ОС (для win32 начиная только с Windows Vista, требуется включение опции BIOS «HPET Support»), где используется системный таймер (его точность не чаще OsTimeSlice — 10-15ms). Для win 2k и младше используется параметр /usepmtimer в boot.ini. см. NTLDR)
- Скорость, обычно в десятки-сотни тысяч раз быстрее (в зависимости от множества факторов). Это очень важно, например, при измерении времени исполнения интенсивных операций, таких, как вызовы функций.
- Не требует переключения в Ring0 в большинстве систем (если команда разрешена в данной ОС).
Проблемы использования
- QueryPerformanceCounter может работать неправильно в Windows Server 2000, Windows Server 2003 и Windows XP.[7]
- При создании коммерческих программ RDTSC потенциально может быть недоступна на конечной системе, поэтому должны быть предусмотрены режимы функционирования, не требующие данной команды.
- Точные замеры:
- невозможность получения точного значения из-за влияния кэшей процессора при обращении к памяти, да и просто исполнение команд требует предвыборки оттуда же. Традиционно решается многократным измерением фрагмента программы.
- возможность переупорядочивания с замеряемыми командами на Out-of-Order процессорах. Решается добавлением сериализующих команд (например, CLD/CLC для Pentium моделей P5, P54[8] или cpuid для более новых) или использованием rdtscp.
- возможная недоступность:
- на старых процессорах (например, 80486) либо на процессорах, реализующих архитектуру x86 не в полном объеме.
- инструкция может быть потенциально превращена в привилегированную (операционной системой установлен 3-й бит в управляющем регистре CR4), и её использование приведет к генерации исключения в программе.
- режим энергосбережения:
- В современных процессорах Intel счетчик TSC не зависит от использования технологий энергосбережения и увеличивается на 1 каждый такт, вне зависимости от того, работал ли процессор или находился в состоянии сна.
- Существует также вопрос периодического динамического автоснижения и автоповышения частот технологиями Cool&Quiet и аналогов от других производителей процессоров, а также технологий псевдоразгона — Intel® Turbo Boost Technology. Для не сильно критических к таймингам систем это обычно обходится периодическим пересчётом частоты, например, в играх (особенно в однопользовательском режиме) и подобных 3D-эмуляторах, а также в реалтайм-счётчиках времени исполнения тех или иных блоков программы.
- псевдовсплески в системах с многопоточным ядром (ядрами) или HyperThreading для случаев очень точных замеров блока команд из-за неучёта загруженности общих процессорных блоков а также кэша и памяти, что верно и для просто мультипроцессорных систем. Простейшее решение — отключить на время тестов HyperThreading в BIOS, при наличии более одного ядра — в BIOS или программно в ОС ограничить число ядер до одного (для win32 — параметр /numproc=1 в c:\boot.ini).
- рассинхронизация в многоядерных системах:
- При инициализации процессоров. В некоторых реализациях счетчики TSC могут иметь синхронные значения на многоядерной системе, в том числе временно, что может ввести программиста в заблуждение о таком же поведение и на других системах.
- Рассинхронизация самих счётчиков в первых многоядерных системах из-за неверно-синхронной инициализации процессоров некоторыми BIOS. Исправляется обновлением BIOS или обновлением операционной системы. Существуют программы для проверки на наличие этой ошибки.[9]
- Порча оперируемого программой значения счётчика в многоядерных системах, когда частота разная или программа не рассчитана на исполнение на многопроцессорной системе, при периодическом автопереключении потока или процесса с одного процессора на другой системой.
- Основной проблемой для применения инструкции rdtsc на многоядерных системах (особенно критично это в случае, когда она используется для измерения временных интервалов) является то, что значения счетчика команд на разных процессорных ядрах могут быть разными (не синхронизированными).
- Для того, чтобы на прикладном уровне можно было отследить факт смены ядра на многоядерных системах, введена инструкция rdtscp, которая, работая аналогично rdtsc, возвращает в регистре ecx дополнительно id процессорного ядра.
Для решения многих проблем рекомендуется фиксирование потока на конкретном процессоре (cpu affinity) и отключение технологий автоматического изменения частоты (в целях энергосбережения или повышения производительности).
Примечания
- ↑ Сериализующий вариант инструкции rdtsc, также читающий IA32_TSC_AUX MSR, в котором часто хранится номер ядра.
- ↑ rdtscp
- ↑ x86/x64 Instruction Set Reference
- ↑ Windows Anti-Debug Reference | Symantec Connect Community
- ↑ Слайд 58 Timing Based Anti-Debugging
- ↑ Tom St. Denis, Simon Johnson, Cryptography for developers.
- ↑ Programs that use the QueryPerformanceCounter function may perform poorly in Windows Server 2000, in Windows Server 2003, and in Windows XP
- ↑ How to optimize for the Pentium family of microprocessors // 1996—2000 by Agner Fog. Chapter «30. Testing speed», перевод
- ↑ ICE Affinity
Ссылки
Категория:- Инструкции x86
Wikimedia Foundation. 2010.