Измерение тактовой частоты процессора

Я пытаюсь измерить скорость процессора. Я не уверен, насколько точен мой метод. В основном я пробовал пустой 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;
}

0

Решение

Это вовсе не измеряет тактовую частоту, а измеряет количество итераций цикла в секунду. Нет правила, согласно которому одна итерация будет выполняться за такт. Это может будь то случай, и ты, возможно, действительно обнаружил, что это так — конечно, с оптимизированным кодом и разумным ЦП, бесполезный цикл не должен выполняться намного медленнее, чем этот. Тем не менее, он может работать с половинной скоростью, некоторые процессоры не могут отключать более 1 взятой ветви каждые 2 цикла. А на эзотерические цели все ставки сняты.

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

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

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

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

Что касается

как узнать, сколько ядер вовлечено в процесс?

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

2

Другие решения

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

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

оказывает такое же влияние на состояние программы, как;

A = C;

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

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

0