¿Mediciones negativas del ciclo de reloj con rdtsc consecutivo?
Estoy escribiendo un código C para medir la cantidad de ciclos de reloj necesarios para adquirir un semáforo. Estoy usando rdtsc, y antes de hacer la medición en el semáforo, llamo a rdtsc dos veces consecutivas, para medir la sobrecarga. Repito esto muchas veces, en un bucle for, y luego uso el valor promedio como sobrecarga rdtsc.
¿Es correcto, para usar el valor promedio, en primer lugar?
No obstante, el gran problema aquí es que a veces obtengo valores negativos para la sobrecarga (no necesariamente el promedio, pero al menos los parciales dentro del bucle for).
Esto también afecta el cálculo consecutivo del número de ciclos de CPU necesarios para elsem_wait()
Operación, que a veces también resulta negativa. Si lo que escribí no está claro, aquí hay una parte del código en el que estoy trabajando.
¿Por qué estoy obteniendo tales valores negativos?
(Nota del editor: verObtener el recuento de ciclos de CPU? para una forma correcta y portátil de obtener la marca de tiempo de 64 bits completa. Un"=A"
La restricción de asm solo obtendrá los 32 bits bajos o altos cuando se compile para x86-64, dependiendo de si la asignación del registro ocurre al seleccionar RAX o RDX para eluint64_t
salida. No va a recogeredx:eax
.)
(2da nota del editor: oops, esa es la respuesta a la razón por la que estamos obteniendo resultados negativos. Todavía vale la pena dejar una nota aquí como advertencia para no copiar estordtsc
implementación.)
#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;
}