Алгоритм измерения частоты процессора сборки
Какие распространенные алгоритмы используются для измерения частоты процессора?
9 ответов
Процессоры Intel после Core Duo поддерживают два специфичных для модели регистра, называемые IA32_MPERF и IA32_APERF.
MPERF считает на максимальной частоте, которую поддерживает ЦП, в то время как APERF считает на текущей частоте.
Фактическая частота определяется как:
Вы можете прочитать их с этим потоком
; read MPERF
mov ecx, 0xe7
rdmsr
mov mperf_var_lo, eax
mov mperf_var_hi, edx
; read APERF
mov ecx, 0xe8
rdmsr
mov aperf_var_lo, eax
mov aperf_var_hi, edx
но обратите внимание, что rdmsr является привилегированной инструкцией и может выполняться только в кольце 0.
Я не знаю, предоставляет ли ОС интерфейс для их чтения, хотя они в основном используются для управления питанием, поэтому такой интерфейс может и не предоставляться.
Я собираюсь встречаться с различными деталями в этом ответе, но какого черта...
Мне пришлось решать эту проблему несколько лет назад на ПК под управлением Windows, поэтому я имел дело с процессорами Intel серии x86, такими как 486, Pentium и так далее. Стандартным алгоритмом в этой ситуации было выполнение длинной серии инструкций DIVide, потому что они, как правило, являются наиболее привязанными к процессору одиночными инструкциями в наборе Intel. Таким образом, предварительная выборка из памяти и другие архитектурные проблемы не оказывают существенного влияния на время выполнения инструкции - очередь предварительной выборки всегда заполнена, а сама инструкция не затрагивает никакую другую память.
Вы бы рассчитывали время, используя часы с наивысшим разрешением, к которым вы могли бы получить доступ в среде, в которой вы работаете. (В моем случае я работал почти во время загрузки на ПК, совместимом, поэтому я непосредственно программировал микросхемы таймера на материнской плате. Не рекомендуется в реальной ОС, обычно есть какой-то подходящий API для вызова в эти дни).
Основная проблема, с которой вам приходится сталкиваться - это разные типы процессоров. В то время Intel, AMD и некоторые мелкие производители, такие как Cyrix, делали процессоры x86. У каждой модели были свои рабочие характеристики по сравнению с инструкцией DIV. Моя функция синхронизации сборки будет просто возвращать количество тактов, выполненных определенным фиксированным количеством инструкций DIV, выполненных в узком цикле.
Поэтому я собрал некоторые временные значения (необработанные возвращаемые значения из этой функции) с реальных ПК, на которых работала каждая модель процессора, и записал их в электронную таблицу в соответствии с известной частотой процессора и типом процессора. У меня действительно был инструмент командной строки, который представлял собой лишь тонкую оболочку вокруг моей функции синхронизации, и я брал диск в компьютерные магазины и получал время от моделей дисплея! (Я работал в очень маленькой компании в то время).
Используя эти необработанные тайминги, я мог построить теоретический график того, какие тайминги я должен получить для любой известной скорости этого конкретного процессора.
Here was the trick: I always hated when you would run a utility and it would announce that your CPU was 99.8 Mhz or whatever. Clearly it was 100 Mhz and there was just a small round-off error in the measurement. In my spreadsheet I recorded the actual speeds that were sold by each processor vendor. Then I would use the plot of actual timings to estimate projected timings for any known speed. But I would build a table of points along the line where the timings should round to the next speed.
In other words, if 100 ticks to do all that repeating dividing meant 500 Mhz, and 200 ticks meant 250 Mhz, then I would build a table that said that anything below 150 was 500 Mhz, and anything above that was 250 Mhz. (Assuming those were the only two speeds available from that chip vendor). It was nice because even if some odd piece of software on the PC was throwing off my timings, the end result would often still be dead on.
Of course now, in these days of overclocking, dynamic clock speeds for power management, and other such trickery, such a scheme would be much less practical. At the very least you'd need to do something to make sure the CPU was in its highest dynamically chosen speed first before running your timing function.
OK, I'll go back to shooing kids off my lawn now.
Один из способов на процессорах Intel x86, поскольку Pentium будет использовать две выборки команды RDTSC с циклом задержки известного времени задержки, например:
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
uint64_t rdtsc(void) {
uint64_t result;
__asm__ __volatile__ ("rdtsc" : "=A" (result));
return result;
}
int main(void) {
uint64_t ts0, ts1;
ts0 = rdtsc();
sleep(1);
ts1 = rdtsc();
printf("clock frequency = %llu\n", ts1 - ts0);
return 0;
}
(на 32-битных платформах с GCC)
RDTSC доступен в кольце 3, если установлен флаг TSC в CR4, что является общим, но не гарантированным. Одним из недостатков этого метода является то, что он уязвим к изменениям масштабирования частоты, влияющим на результат, если они происходят внутри задержки. Чтобы снизить вероятность того, что вы сможете выполнить код, который будет загружать процессор и постоянно опрашивать системное время, чтобы увидеть, истек ли ваш период задержки, сохранить процессор в состоянии максимальной частоты.
На процессорах Intel распространенный метод получения текущей (средней) частоты процессора - вычисление ее с помощью нескольких счетчиков процессора:
CPU_freq = tsc_freq * (aperf_t1 - aperf_t0) / (mperf_t1 - mperf_t0)
TSC (Time Stamp Counter) может быть считан из пользовательского пространства с выделенными х86, но его частота должна быть определена путем калибровки с часами. Лучший подход - получить частоту TSC из ядра (которое уже выполнило калибровку).
Счетчики aperf и mperf представляют собой регистры MSR для конкретных моделей, для доступа к которым требуются привилегии root. Опять же, есть специальные инструкции x86 для доступа к MSR.
Поскольку скорость счетчика mperf прямо пропорциональна скорости TSC, а скорость aperf прямо пропорциональна частоте процессора, вы получаете частоту процессора с помощью приведенного выше уравнения.
Конечно, если в вашем t0 - t1
дельта времени (например, из-за масштабирования частоты) вы получите среднюю частоту процессора с помощью этого метода.
Я написал небольшую утилиту cpufreq, которую можно использовать для тестирования этого метода.
Смотрите также:
Я использую следующий (псевдо) алгоритм:
basetime=time(); /* time returns seconds */
while (time()==basetime);
stclk=rdtsc(); /* rdtsc is an assembly instruction */
basetime=time();
while (time()==basetime
endclk=rdtsc();
nclks=encdclk-stclk;
На данный момент вы можете предположить, что вы определили тактовую частоту, но даже если она кажется правильной, ее можно улучшить.
Все ПК содержат устройство PIT (Programmable Interval Timer), которое содержит счетчики, которые (использовались) для последовательных портов и системных часов. Питался с частотой 1193182 Гц. Системный тактовый счетчик был установлен на самое высокое значение обратного отсчета (65536), в результате чего системная тактовая частота составляла 1193182/65536 => 18,2065 Гц или один раз каждые 54,925 миллисекунд.
Поэтому количество тактов, необходимое для приращения часов к следующей секунде, будет зависеть. Обычно требуется 18 тиков, а иногда 19. Это можно сделать, выполнив алгоритм (см. Выше) дважды и сохранив результаты. Два результата будут либо эквивалентны двум последовательностям по 18 тиков, либо одному из 18 и одному 19. Два 19 подряд не появятся. Поэтому, взяв меньшее из двух результатов, вы получите 18 тиковых секунд. Откорректируйте этот результат, умножив на 18,2065 и поделив на 18,0 или, используя целочисленную арифметику, умножьте на 182065, прибавьте 90000 и разделите на 180000. 90000 - это половина от 180000 и есть для округления. Если вы выбираете вычисления с целочисленным маршрутом, убедитесь, что вы используете 64-битное умножение и деление.
Теперь у вас будет тактовая частота процессора x в Гц, которую можно преобразовать в кГц ((x+500)/1000) или МГц ((x+5000000)/1000000). 500 и 500000 составляют половину от 1000 и 1000000 соответственно и предназначены для округления. Для расчета МГц не используйте значение кГц, поскольку могут возникнуть проблемы с округлением. Используйте значение Гц и второй алгоритм.
Один из вариантов - определить частоту процессора, выполнив код с известными инструкциями для цикла
Эта функциональность содержится в 7zip, так как около v9.20 я думаю.
> 7z b
7-Zip 9.38 beta Copyright (c) 1999-2014 Igor Pavlov 2015-01-03
CPU Freq: 4266 4000 4266 4000 2723 4129 3261 3644 3362
Окончательное число должно быть правильным (и на моем ПК и многих других я нашел его достаточно правильным - тест выполняется очень быстро, поэтому турбо может не сработать, а серверы, установленные в режимах Сбалансированный / Энергосбережение, скорее всего, дают показания около 1 ГГц)
Исходный код находится на GitHub (Официальный источник загружен с 7-zip.org)
Самая значительная часть:
#define YY1 sum += val; sum ^= val;
#define YY3 YY1 YY1 YY1 YY1
#define YY5 YY3 YY3 YY3 YY3
#define YY7 YY5 YY5 YY5 YY5
static const UInt32 kNumFreqCommands = 128;
EXTERN_C_BEGIN
static UInt32 CountCpuFreq(UInt32 sum, UInt32 num, UInt32 val)
{
for (UInt32 i = 0; i < num; i++)
{
YY7
}
return sum;
}
EXTERN_C_END
Это было целью таких вещей, как BogoMIPS, но сейчас процессоры намного сложнее. Суперскалярные процессоры могут выдавать несколько команд за такт, делая любые измерения, основанные на подсчете тактов, для выполнения блока инструкций с высокой точностью.
Частоты процессора также являются переменными в зависимости от предлагаемой нагрузки и / или температуры. Тот факт, что процессор в настоящее время работает на частоте 800 МГц, не означает, что он всегда будет работать на частоте 800 МГц, он может увеличивать или уменьшать при необходимости.
Если вам действительно нужно знать тактовую частоту, она должна быть передана в качестве параметра. ЭСППЗУ на плате будет обеспечивать базовую частоту, и если тактовая частота может меняться, вам понадобится прочитать регистры состояния питания ЦП (или сделать вызов ОС), чтобы узнать частоту в этот момент.
С учетом всего сказанного, могут быть и другие способы выполнить то, что вы пытаетесь сделать. Например, если вы хотите выполнить высокоточные измерения того, сколько времени занимает определенный путь кода, ЦП, скорее всего, имеет счетчики производительности, работающие с фиксированной частотой, которые являются лучшим показателем времени настенного времени, чем считывание регистра счетчика тиков.
"lmbench" предоставляет частотный алгоритм процессора, переносимый для разных архитектур.
Он запускает несколько разных циклов, и тактовая частота процессора является наибольшим общим делителем частот выполнения различных циклов.
этот метод всегда должен работать, когда мы можем получить циклы с относительно простым числом циклов.
Я не уверен, зачем вам нужна сборка для этого. Если вы работаете на машине с файловой системой /proc, то запустите:
> cat /proc/cpuinfo
может дать вам то, что вам нужно.