Я пишу код C для измерения количества тактовых циклов, необходимых для получения семафора. Я использую rdtsc, и прежде чем делать измерения на семафоре, я вызываю rdtsc два раза подряд, чтобы измерить накладные расходы. Я повторяю это много раз, в for-loop, а затем использую среднее значение как служебные данные rdtsc.
Правильно ли это, прежде всего, использовать среднее значение?
Тем не менее, большая проблема заключается в том, что иногда я получаю отрицательные значения для служебных (не обязательно усредненных), но, по крайней мере, частичных внутри цикла for.
Это также влияет на последовательный расчет количества циклов процессора, необходимых для операции sem_wait()
, которая иногда также оказывается отрицательной. Если то, что я написал, неясно, вот часть кода, над которым я работаю.
Почему я получаю такие отрицательные значения?
(примечание редактора: см. " Получить кол-во циклов процессора" для правильного и переносимого способа получения полной 64-битной метки времени. Ограничение asm "=A"
будет получать только минимальные или высокие 32 бита при компиляции для x86-64, в зависимости от происходит ли распределение регистров, чтобы выбрать RAX или RDX для вывода uint64_t
. Он не будет выбирать edx:eax
.)
(редактор 2-й ноты: oops, ответ на вопрос, почему мы получаем отрицательные результаты. Стоит оставить примечание здесь как предупреждение не копировать эту реализацию rdtsc
.)
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
static inline uint64_t get_cycles()
{
uint64_t t;
// editor note: "=A" is unsafe for this in x86-64
__asm volatile ("rdtsc" : "=A"(t));
return t;
}
int num_measures = 10;
int main ()
{
int i, value, res1, res2;
uint64_t c1, c2;
int tsccost, tot, a;
tot=0;
for(i=0; i<num_measures; i++)
{
c1 = get_cycles();
c2 = get_cycles();
tsccost=(int)(c2-c1);
if(tsccost<0)
{
printf("#### ERROR!!! ");
printf("rdtsc took %d clock cycles\n", tsccost);
return 1;
}
tot = tot+tsccost;
}
tsccost=tot/num_measures;
printf("rdtsc takes on average: %d clock cycles\n", tsccost);
return EXIT_SUCCESS;
}