Разность таймеров
Современные материнские платы несут на борту несколько независимых таймеров, которые никто не калибровал и каждый из которых врет слегка по своему. Различные ядра используют различные таймеры для подсчета времени и системного планирования, поэтому отталкиваться от API-функций типа GetTickCount или QueryPerfomanceCounter для сравнения производительности ядер категорически недопустимо! Ну во всяком случае без их предварительной калибровки.
Первым (а на IBMXT еще и единственным) возник программируемый таймер интервалов – Programmable Interval Timer
или сокращенно PIT, базирующейся на микросхеме Intel 8254 (сейчас – 82C54), и тактируемый частотой 1.19318 MHz (сейчас – либо 1.19318, либо 14.31818 MHz, причем последняя встречается намного чаще), что обеспечивало ему превосходную по тем временам точность измерений – порядка 0.84 мс (~1 мс с учетом накладных расходов). В Windows продолжительность одного тика таймера составляет 10 мс. Каждые 10 мс таймер дергает прерыванием и закрепленный за ним обработчик увеличивает системное время на эту же величину. Если обработчик по каким-либо причинам проморгает таймерное прерывание (аппаратные прерывания запрещены инструкцией CLI или перепрограммированием PIC-контроллера), системное время начнет отставать от реального, существенно снижая точность измерений. Хуже того, размеренность хода PIT'а далеко неидеальна и варьируется в довольно широких пределах. Windows использует PIC таймер в основном для планирования потоков, а для измерения времени стремится использовать другие, более точные таймеры, и переходит на PIT только тогда, когда ни один из них недоступен.
Таймер часов реального времени (Real Time Clock
или сокращенно RTC), впервые появившийся в IBM AT, обычно тактируется частотой 32.768 kHz, автоматически обновляя счетчик времени в CMOS, что не требует наличия программного обработчика прерываний. Частота обновления по умолчанию составляет 100 HZ, но при желании RTC-таймер может быть перепрограммирован и тогда часы будут идти или медленнее, или быстрее. Точность показаний зависит как от состояния питающей батарейки (которая вообще-то, никакая не батарейка, а настоящий литиевый аккумулятор, но это уже не важно), так и от добротности реализации микросхемы RTC со всеми обслуживающими ее компонентами. По заверениям производителей среднее время ухода за день составляет порядка 1-2 сек, однако, имеющиеся у меня материнские платы врут намного сильнее, к тому же некоторые из них обнаруживают значительные "биения" на временных интервалах порядка десятых долей секунды, что отнюдь не способствует точности измерений. К тому же некоторые версии Windows периодически синхронизуют системное время с часами реального времени, что еще больше подрывает доверие к системному времени. Используя его для измерения продолжительности тех или иных процессов, вы можете получить очень странный результат. Часы реального времени используют многие тестовые программы и перепрограммирование RTC-таймера позволяет фальсифицировать результат. Windows 2000 использует RTC только для периодической синхронизации с системными часами.
Усовершенствованный контроллер прерываний (Advanced Programmable Interrupt Controller или сокращенно APIC), в основном использующийся в многопроцессорных системах, помимо прочей оснастки включает в себя и некоторую пародию на таймер, предназначенный для планирования потоков и непригодный ни для каких измерений ввиду своей невысокой точности. Однако, по непонятным причинам, APIC-ядра используют APIC-таймер в качестве основного таймера системы, при этом величина одного "тика" составляет уже не 10 мс, а 15 мс. Естественно, часы идут с прежней скоростью, но политика планирования существенно изменяется – с увеличением кванта сокращаются накладные расходы на переключение контекстов, но ухудшается плавность коммутации между ними. Использовать показания счетчика системного времени для сравнения производительности APIC-ядер с другими ядрами недопустимо, т. к. полученный результат будет заведомо ложным.
Материнские платы, поддерживающие ACPI (Advanced Configuration and Power Interface), имеют специальный таймер, обычно управляемый менеджером электропитания и потому называющийся Power Management Timer или сокращенно PM. Еще его называют ACPI-таймером. Штатно от тактируется частой 3.579545 MHz (тактовая частота PIT'а разделенная на четыре), что обеспечивает точность измерений порядка ~0.3 мс. ACPI-ядра используют PM-таймер в качестве основного таймера системы, чем сами не рады. Чипсеты от VIA, SIS, ALI, RCC не вполне корректно реализуют PM-таймер, что приводит к обвальному падению производительности операционной системы и снижению надежности ее работы. Проблема лечится установкой соответствующего пакета обновления, подробнее о котором можно прочитать в технической заметке Q266344. Разумеется, исправить аппаратную проблему (а в данном случае мы имеем дело именно с ней) программными средствами невозможно и ее можно лишь обойти. Но даже на правильном чипсете при высокой загрузке PCI-шины PM-таймер не успевает современно передавать свои тики и хотя они при этом не пропадают, обновление счетчика времени происходит "рывками", для преодоления которых Microsoft рекомендует сверять показания PM с показаниями PIC'а/APIC'а или RTC. И, если PM неожиданно прыгнет вперед (jump forward), обогнав своих соплеменников, этот замер должен аннулироваться как недействительный.
Современные чипсеты (и, в частности, Intel 845) содержат специальный высокоточный таймер (High Precision Event Timers или сокращенно HPET), тактируемый частой от 10 MHz, при которой время одного тика "тика" составляет от 0.1 мс при точности порядка ±0.2% на интервалах от 1 мс до 100 мс. Это действительно рекордно высокая точность, по крайней мере на порядок прерывающая точность всех остальных таймеров, однако, HPET все еще остается завидной экзотикой и чипсеты с его поддержкой пока еще не очень широко распространены.
Помимо этого на материнской плате можно найти множество таймеров, например, PCI Latency Timer или десятки таймеров, обслуживающих чипсет, шины, память и прочие системные устройства. Многие из них тактируются частотами PCI или AGP шины, что обеспечивает достаточно высокую точность измерений (ниже чем у HPET, но существенно выше, чем у PM). К сожалению, они в своей массе не стандартизированы и на каждой материнской плате реализуются по своему, если вообще реализуются.
Некоторые используют в качестве таймера команду RDTSC, считывающую показания внутреннего счетчика процессора, каждый такт увеличивающегося на постоянную величину (как правило единицу). Для профилировки машинного кода она подходит на ура, но вот на роль беспристрастного метронома уже не тянет. Некоторые APCI-контроллеры динамически изменяют частоту процессора или усыпляют его в паузах между работой для лучшего охлаждения. Как следствие – непосредственное преобразование процессорных тактов в истинное время оказывается невозможным.
Утилиту для оценки разности хода нескольких таймеров можно скачать например отсюда: http://www.overclockers.ru/cgi-bin/files/download.cgi?file=320&filename=timertest.rar. И если, выяснится, что ваши таймеры идут неодинаково, для сравнения производительности различных ядер будет необходимо ограничится лишь одним из них. Надежнее всего использовать для снятия показаний свой собственный драйвер, поскольку стратегия выбора таймеров ядром системы в общем случае непредсказуема и может отличается от выше описанной.