Medições negativas do ciclo de clock com rdtsc back-to-back?
Eu estou escrevendo um código C para medir o número de ciclos de clock necessários para adquirir um semáforo. Estou usando o rdtsc e, antes de fazer a medição no semáforo, chamo o rdtsc duas vezes consecutivas para medir a sobrecarga. Eu repito isso muitas vezes, em um loop for, e então eu uso o valor médio como sobrecarga de rdtsc.
Isso está correto, para usar o valor médio, em primeiro lugar?
No entanto, o grande problema aqui é que às vezes recebo valores negativos para a sobrecarga (não necessariamente a média, mas pelo menos os parciais dentro do loop for).
Isso também afeta o cálculo consecutivo do número de ciclos de cpu necessários para osem_wait()
operação, que às vezes também se revela negativa. Se o que eu escrevi não está claro, aqui está uma parte do código em que estou trabalhando.
Por que estou recebendo valores tão negativos?
(nota do editor: verObter contagem de ciclos da CPU? para obter uma maneira correta e portátil de obter o registro de data e hora completo de 64 bits. A"=A"
A restrição ASM só irá obter os 32 bits baixos ou altos quando compilados para x86-64, dependendo se a alocação de registradores acontece para escolher RAX ou RDX para ouint64_t
saída. Não vai pegaredx:eax
.)
(segunda nota do editor: oops, essa é a resposta para porque estamos obtendo resultados negativos. Ainda vale a pena deixar uma nota aqui como um aviso para não copiarrdtsc
implementação.)
#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;
}