Pomiary cykli zegara ujemnego z rdtsc back-to-back?
Piszę kod C do pomiaru liczby cykli zegara potrzebnych do uzyskania semafora. Używam rdtsc, a przed wykonaniem pomiaru na semaforze, wywołuję rdtsc dwa razy z rzędu, aby zmierzyć obciążenie. Powtarzam to wiele razy w pętli for, a następnie używam średniej wartości jako narzutu rdtsc.
Czy to poprawne, aby użyć średniej wartości, przede wszystkim?
Niemniej jednak dużym problemem jest to, że czasami otrzymuję ujemne wartości narzutów (niekoniecznie uśrednionych, ale przynajmniej częściowych wewnątrz pętli for).
Ma to również wpływ na kolejne obliczenia liczby cykli procesora potrzebnych dlasem_wait()
operacja, która czasami również okazuje się negatywna. Jeśli to, co napisałem, nie jest jasne, tutaj jest część kodu, nad którym pracuję.
Dlaczego otrzymuję takie negatywne wartości?
(uwaga redaktora: patrzUzyskać liczbę cykli procesora? dla poprawnego i przenośnego sposobu uzyskania pełnego 64-bitowego znacznika czasu. Na"=A"
Ograniczenie asm otrzyma tylko 32-bitowe niskie lub wysokie bity podczas kompilacji dla x86-64, w zależności od tego, czy przydział rejestrów zdarzy się po wybraniu RAX lub RDX dlauint64_t
wydajność. Nie wybierzeedx:eax
.)
(druga uwaga redaktora: oops, to jest odpowiedź na pytanie, dlaczego otrzymujemy negatywne wyniki. Wciąż warto zostawić tutaj notatkę jako ostrzeżenie, aby nie kopiować tegordtsc
realizacja.)
#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's 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;
}