2016-06-18 6 views
0

Я пытаюсь измерить скорость CPU.I не уверен, насколько мой метод является точным. Основном, я попробовал пустой for цикл со значениями как UINT_MAX но программа завершается быстро, поэтому я попытался UINT_MAX * 3 и так далее ...Измерение тактовой частоты процессора

Тогда я понял, что компилятор оптимизирует расстояние петли, так что я добавил volatile для предотвращения оптимизации. Следующая программа занимает примерно 1,5 секунды. Я хочу знать, насколько точным является этот алгоритм для измерения тактовой частоты. Кроме того, как я узнаю, сколько ядро ​​задействовано в этом процессе?

#include <iostream> 
#include <limits.h> 
#include <time.h> 

using namespace std; 

int main(void) 
{ 
    volatile int v_obj = 0; 
    unsigned long A, B = 0, C = UINT32_MAX; 

    clock_t t1, t2; 
    t1 = clock(); 

    for (A = 0; A < C; A++) { 
     (void)v_obj; 
    } 
    t2 = clock(); 
    std::cout << (double)(t2 - t1)/CLOCKS_PER_SEC << std::endl; 

    double t = (double)(t2 - t1)/CLOCKS_PER_SEC; 
    unsigned long clock_speed = (unsigned long)(C/t); 

    std::cout << "Clock speed : " << clock_speed << std::endl; 
    return 0; 
} 
+1

Поскольку современные процессоры имеют переменную тактовую частоту и несколько ядер; запуск такого рода тестов будет только измерять максимальную тактовую частоту 1 ядро. –

+0

Поставив там «volatile», вы замедлили свою скорость до скорости памяти, побеждая цель измерения скорости процессора. –

+0

@DavidSchwartz Итак, как именно вы предотвращаете оптимизацию? –

ответ

2

Это не измеряет часы скорость вообще, он измеряет, сколько циклов может выполняться в секунду. Нет правила, согласно которому одна итерация будет выполняться за такт. Это может быть может, и вы, возможно, действительно обнаружили, что это так - конечно, с оптимизированным кодом и разумным процессором, бесполезный цикл не должен работать намного медленнее, чем это. Он может работать на половинной скорости, хотя некоторые процессоры не могут удалять более 1 взятой ветки каждые 2 цикла. И по эзотерическим целям все ставки отключены.

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

  1. Если измерить, сколько времени настенных часов цикл принимает, вы должны знать (по крайней мере приблизительно) количество циклов на итерацию. Это довольно сложная проблема в сборке, требующая довольно подробного знания ожидаемых микроархитектур (может быть, длинная цепочка зависимых команд, каждая из которых может разумно принимать только один цикл, например add eax, 1? Достаточно длинная цепочка, что различия в пропускной способности теста/ветки становятся небольшими достаточно, чтобы игнорировать), поэтому очевидно, что все, что вы там делаете, не переносимо и будет иметь встроенные в него предположения, может стать ложным (на самом деле есть другой ответ на SO, который делает это, и предполагает, что у addps есть латентность 3, t больше на Skylake, и не было на старых AMD). В C? Откажитесь сейчас. Компилятор может перекатить какой-то генератор случайных кодов, и полагаться на это, чтобы быть разумным, это как делать то же самое с медведем. Угадайте количество циклов на итерацию код, который вы ни контролируете, ни даже не знаете. - это просто глупость. Если это только на вашей собственной машине, вы можете проверить код, но тогда вы могли бы просто проверить тактовую частоту вручную тоже.

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

Так что, если вы делаете это для получения фактической информации, а не просто для того, чтобы пообщаться, вам стоит просто спросить ОС. Для Windows запросите WMI для CurrentClockSpeed ​​или MaxClockSpeed, в зависимости от того, что вы хотите. В Linux есть вещи в /proc/cpuinfo. Все еще не портативен, но тогда решения нет.

Что касается

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

1. Конечно, ваша нить может мигрировать между ядрами, но поскольку у вас есть только одна нить, она находится только на одном ядре в любое время.

+0

В Linux есть команда 'perf stat// ', которая будет отслеживать и сообщать среднюю тактовую частоту процессора для любой программы« ./program »(как X.XX GHz). Он использует Hardware PMU - счетчики производительности для подсчета реальных циклов процессора (не tsc), используемых для запуска программы, а также учета времени (событие программного обеспечения для задач). Реальные счетчики часов могут быть доступны с API-интерфейсом 'perf_events' или с некоторыми портативными lib, такими как PAPI, непосредственно из пользовательского пространства. – osgx

0

Хороший оптимизатор может удалить петлю, так как

for (A = 0; A < C; A++) { 
    (void)v_obj; 
} 

имеет тот же эффект на состояние программы в виде;

A = C; 

Таким образом, оптимизатор полностью освобождает ваш цикл.

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

+0

Неужели 'volatile 'пугает компилятор в подчинении? E: по-видимому, не – harold