Подтвердить что ты не робот

Сборочный алгоритм измерения частоты процессора

Каковы общие алгоритмы, используемые для измерения частоты процессора?

4b9b3361

Ответ 1

Процессоры Intel после Core Duo поддерживают два регистра конкретных моделей, называемые IA32_MPERF и IA32_APERF.
MPERF рассчитывается на максимальной частоте, поддерживаемой ЦП, в то время как APERF рассчитывается с фактической текущей частотой.

Фактическая частота определяется:

freq = max_frequency * APERF / MPERF

Вы можете прочитать их с помощью этого потока

; 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.

Я не знаю, предоставляет ли ОС интерфейс для их чтения, хотя основное их назначение - управление питанием, поэтому он не может обеспечить такой интерфейс.

Ответ 2

Я собираюсь встречаться с различными подробностями в этом ответе, но что за черт...

Мне пришлось решить эту проблему несколько лет назад на компьютерах под управлением Windows, поэтому я имел дело с процессорами серии Intel x86, такими как 486, Pentium и так далее. Стандартный алгоритм в этой ситуации состоял в том, чтобы сделать длинную серию инструкций DIVide, потому что они обычно являются самыми одиночными инструкциями с процессором в наборе Intel. Таким образом, предварительная выборка памяти и другие архитектурные проблемы существенно не влияют на время выполнения команды - очередь предварительной выборки всегда заполнена, и сама инструкция не касается другой памяти.

Вы бы потратили время, используя часы с самым высоким разрешением, с которыми вы могли бы получить доступ в среде, в которой вы работаете. (В моем случае я работал около времени загрузки на ПК, поэтому я напрямую программировал таймеры на материнская плата. Не рекомендуется в реальной ОС, обычно там есть соответствующий API для вызова в эти дни).

Основной проблемой, с которой вам приходится иметь дело, являются разные типы процессоров. В то время были Intel, AMD и некоторые более мелкие вендоры, такие как Cyrix, делающие процессоры x86. Каждая модель имела свои характеристики производительности по сравнению с инструкцией DIV. Моя функция синхронизации сборки просто вернет несколько тактовых циклов, сделанных определенным фиксированным числом команд DIV, выполненных в узком цикле.

Так что я сделал, чтобы собрать некоторые тайминги (необработанные возвращаемые значения из этой функции) с реальных ПК, на которых запускалась каждая модель процессора, которую я хотел найти, и записывать их в электронную таблицу с известной скоростью процессора и типом процессора. У меня на самом деле был инструмент командной строки, который был просто тонкой оболочкой вокруг моей функции синхронизации, и я бы взял диск в компьютерные магазины и отключил таймеры от моделей дисплея! (В то время я работал в очень маленькой компании).

Используя эти необработанные тайминги, я мог бы построить теоретический график того, какие тайминги я должен получить для любой известной скорости этого конкретного процессора.

Вот трюк: я всегда ненавидел, когда вы запускали утилиту, и объявлял, что ваш процессор был 99,8 МГц или что-то еще. Очевидно, что это было 100 МГц, и в измерении была только небольшая ошибка округления. В моей таблице я записал фактические скорости, которые были проданы каждым производителем процессоров. Затем я бы использовал график фактических таймингов для оценки прогнозируемых таймингов для любой известной скорости. Но я бы построил таблицу точек вдоль линии, где тайминг должен округлить до следующей скорости.

Другими словами, если 100 тиков, чтобы сделать все, что повторяя разделение, означало 500 Mhz, а 200 тиков означало 250 Mhz, тогда я бы построил таблицу, в которой говорилось, что что-то ниже 150 было 500 МГц, а что-то выше, чем 250 Mhz, (Предполагая, что это были только две скорости, доступные от этого поставщика чипов). Это было хорошо, потому что, даже если какая-то странная часть программного обеспечения на ПК отбрасывала мои тайминги, конечный результат часто все еще был бы мертв.

Конечно, в эти дни разгона, динамических тактовых скоростей для управления питанием и других подобных обманов такая схема была бы гораздо менее практичной. По крайней мере, вам нужно будет что-то сделать, чтобы убедиться, что процессор был на самой высокой динамически выбранной скорости, прежде чем запускать вашу функцию синхронизации.

Хорошо, я вернусь к тому, чтобы отвлечь детей от моей лужайки.

Ответ 3

Один из способов на процессоре Intel x86 Intel 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, который является общим, но не гарантированным. Один из недостатков этого метода заключается в том, что он уязвим для изменений частотного масштабирования, влияющих на результат, если они происходят внутри задержки. Чтобы уменьшить это, вы можете выполнить код, который заставляет процессор загружаться и постоянно проверять системное время, чтобы узнать, истек ли срок задержки, чтобы поддерживать CPU в состоянии с высокой частотой.

Ответ 4

Я использую следующий (псевдо) алгоритм:

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 (программируемый интервал таймера), которое содержит счетчики, которые используются (используются) для последовательных портов и системных часов. Его подавали с частотой 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 соответственно и предназначены для округления. Чтобы вычислить МГц, не переходите через значение kHz, так как могут возникать проблемы округления. Используйте значение Hz и второй алгоритм.

Ответ 5

Это было намерение таких вещей, как BogoMIPS, но в наши дни процессоры намного сложнее, Суперскалярные ЦП могут выдавать несколько инструкций за такт, делая любое измерение, основанное на подсчете тактовых циклов, чтобы выполнить блок инструкций очень неточным.

Частоты процессора также варьируются в зависимости от предлагаемой нагрузки и/или температуры. Тот факт, что процессор в настоящее время работает на частоте 800 МГц, не означает, что он всегда будет работать на частоте 800 МГц, он может дросселировать вверх или вниз по мере необходимости.

Если вам действительно нужно знать тактовую частоту, он должен быть передан как параметр. EEPROM на плате будет обеспечивать базовую частоту, и если часы могут меняться, вам нужно будет прочитать регистры состояния процессора (или сделать вызов ОС), чтобы узнать частоту в этот момент.

Со всем сказанным, могут быть другие способы выполнить то, что вы пытаетесь сделать. Например, если вы хотите сделать высокоточные измерения того, сколько времени занимает определенная кодовая страница, у CPU, вероятно, есть счетчики производительности, работающие на фиксированной частоте, которые являются лучшим показателем времени настенных часов, чем чтение регистра счетчика тиков.

Ответ 6

"lmbench" предоставляет алгоритм частоты процессора, переносимый для разных архитектур.

Он запускает несколько разных циклов, а тактовая частота процессора является наибольшим общим делителем частот выполнения различных циклов.

этот метод всегда должен работать, когда мы можем получить циклы с количеством циклов, которые являются взаимно простыми.

http://www.bitmover.com/lmbench/

Ответ 7

Я не уверен, зачем вам нужна сборка для этого. Если вы находитесь на машине с файловой системой /proc, выполните следующую команду:

> cat /proc/cpuinfo

может дать вам то, что вам нужно.

Ответ 8

Быстрый google на AMD и Intel показывает, что CPUID должен предоставить вам максимальную частоту процессора.

Ответ 9

Один из вариантов - определить частоту процессора, запустив код с известными инструкциями на цикл

Эта функциональность содержится в 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

Конечный номер должен быть правильным (и на моем ПК, и на многих других, я нашел, что это было совершенно правильно - тест проходит очень быстро, поэтому турбо не может ударить, а серверы настроены в режимах Balanced/Power Save скорее всего, дают показания около 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