#ifndef __TIMMING__H__
#define __TIMMING__H__
#include <stdio.h>
#include <stdlib.h>
#ifndef __GNUC__
# error CC != GCC
#endif
/* High accuracy timing */
#if defined (__i386__) || defined(__amd64__)
#define read_rdtsc_before(time) \
__asm__ __volatile__( \
".align 64\n\t" \
"xor %%eax,%%eax\n\t" \
"cpuid\n\t" \
"rdtsc\n\t" \
"mov %%eax,(%0)\n\t" \
"mov %%edx,4(%0)\n\t" \
"xor %%eax,%%eax\n\t" \
"cpuid\n\t" \
: /* no output */ \
: "S"(&time) \
: "eax", "ebx", "ecx", "edx", "memory")
#define read_rdtsc_after(time) \
__asm__ __volatile__( \
"xor %%eax,%%eax\n\t" \
"cpuid\n\t" \
"rdtsc\n\t" \
"mov %%eax,(%0)\n\t" \
"mov %%edx,4(%0)\n\t" \
"xor %%eax,%%eax\n\t" \
"cpuid\n\t" \
: /* no output */ \
: "S"(&time) \
: "eax", "ebx", "ecx", "edx", "memory")
#elif defined (__ia64)
#define rdtsc() \
({ unsigned long long int x; \
__asm__ __volatile__("mov %0=ar.itc" : "=r"(x) :: "memory");\
x; })
#define read_rdtsc_before(time) (time = rdtsc())
#define read_rdtsc_after(time) (time = rdtsc())
#elif defined (__alpha)
#define rdtsc() \
({ unsigned long long int x; \
__asm__ volatile ("rpcc %0\n\t" : "=r" (x)); \
x; })
#define read_rdtsc_before(time) (time = rdtsc())
#define read_rdtsc_after(time) (time = rdtsc())
#else
# error Unsupported CPU
#endif
/* First loop : We do several measures and keep the minimum to avoid counting
* hardware interruption cycles.
* Second loop: We do several measures until we are sure we are in the same
* clock_t frame, so that we are sure no task switching has been done (removed s
ince it introduced problems with system call and empty cache).
* The filling of the CPU cache is done because we do several loops, and get the
min.
* Declaring num_cycle as "volatile" is to avoid optimisation when it is possibl
e (To properly calcul overhead).
* overhead is calculated outside by a call to: overhead = MEASURE("overhead", ;
)
* Use a lot the preprocessor.
* It is a macro to be very flexible.
*/
static unsigned long long int overhead = 0;
#define NUM_TRY 4327
#define MEASURE(TEST) \
({ \
volatile unsigned long long int num_cycle, num_cycle2, min_num_cycle; \
int i_; \
min_num_cycle = 0xFFFFFFFFFFFFFFFFLL; \
for(i_ = 0 ; i_ < NUM_TRY ; i_++) \
{ \
read_rdtsc_before(num_cycle); \
TEST; \
read_rdtsc_after(num_cycle2); \
num_cycle = num_cycle2 - num_cycle - overhead; \
if (num_cycle < min_num_cycle) \
min_num_cycle = num_cycle; \
} \
min_num_cycle; })
/*
* It is few probable that an int triggers during the 2 calls of rdtsc
* but it is possible (and it occurs too!).
* But it is VERY unprobable that an int triggers for the minimum of 1000
* measures of the difference between 2 calls of rdtsc
*/
#define CALCUL_OVERHEAD (overhead = 0, overhead = MEASURE((void) 0) )
#endif
Puis pour utiliser:
{
...
unsigned long long int t;
CALCUL_OVERHEAD;
t = measure (mafonction(x,y) );