Некоторое время назад я задал вопрос о переполнении стека и мне показали, как выполнить код операции rdtsc в C ++.Недавно я создал эталонную функцию с использованием rdtsc следующим образом:
inline unsigned long long rdtsc() {
unsigned int lo, hi;
asm volatile (
"cpuid \n"
"rdtsc"
: "=a"(lo), "=d"(hi) /* outputs */
: "a"(0) /* inputs */
: "%ebx", "%ecx"); /* clobbers*/
return ((unsigned long long)lo) | (((unsigned long long)hi) << 32);
}
typedef uint64_t (*FuncOneInt)(uint32_t n);
/**
time a function that takes an integer parameter and returns a 64 bit number
Since this is capable of timing in clock cycles, we won't have to do it a
huge number of times and divide, we can literally count clocks.
Don't forget that everything takes time including getting into and out of the
function. You may want to time an empty function. The time to do the computation
can be compute by taking the time of the function you want minus the empty one.
*/
void clockBench(const char* msg, uint32_t n, FuncOneInt f) {
uint64_t t0 = rdtsc();
uint64_t r = f(n);
uint64_t t1 = rdtsc();
std::cout << msg << "n=" << n << "\telapsed=" << (t1-t0) << '\n';
}
Поэтому я предположил, что если бы я тестировал функцию, у меня было бы (примерно) количество тактов, которое потребовалось для ее выполнения.Я также предположил, что если я хочу вычесть количество тактов, которое потребовалось, чтобы войти или выйти из функции, я должен сравнить пустую функцию, а затем написать одну с нужным кодом внутри.
Вотпример:
uint64_t empty(uint32_t n) {
return 0;
}
uint64_t sum1Ton(uint32_t n) {
uint64_t s = 0;
for (int i = 1; i <= n; i++)
s += i;
return s;
}
Код скомпилирован с использованием
g++ -g -O2
Я мог бы понять, есть ли какая-либо ошибка из-за прерывания или какого-то другого условия, но учитывая, что эти процедуры короткие, и n выбран, чтобы быть маленьким, я предположил, что я мог видеть реальные числа.Но, к моему удивлению, это результат двух последовательных прогонов
empty n=100 elapsed=438
Sum 1 to n=100 elapsed=887
empty n=100 elapsed=357
Sum 1 to n=100 elapsed=347
Постоянно пустая функция показывает, что она занимает намного больше времени, чем должна.
В конце концов, есть только несколькоинструкции по входу и выходу из функции.Настоящая работа выполняется в цикле.Не берите в голову тот факт, что разница огромна.Во втором запуске пустая функция утверждает, что она берет 357 тактов, а сумма занимает меньше, что смешно.
Что происходит?