Это зависит от изменений, которые вы наблюдаете.В современных компьютерах все разработано для статистической оптимизации среднего времени работы.Но многие архитектурные особенности основаны на статистике и в зависимости от начальных условий могут привести к очень разному времени выполнения.Это в основном кеши и предикторы ветвления.Нормально иметь вариации около 20-30% во время выполнения.И мы провели эксперименты на системах без ОС, использующих железо, и те же самые стойки поведения.
Вот программа, которая измеряет время с помощью счетчика меток времени (циклов).Можно проверить две простые функции.Один - это просто нулевой вектор, а второй - набор тестов для случайного (но всегда идентичного) вектора.
#include <stdio.h>
#include <stdlib.h>
#define N 1000000
#define TYPE int
#define ZERO 0
static unsigned long long start_timer() ;
static unsigned long long stop_timer() ;
static double dtime(long long debut, long long fin);
#ifdef __i386__
# define RDTSC_DIRTY "%eax", "%ebx", "%ecx", "%edx"
#elif __x86_64__
# define RDTSC_DIRTY "%rax", "%rbx", "%rcx", "%rdx"
#else
# error unknown platform
#endif
static inline unsigned long long start_timer()
{
unsigned int hi = 0, lo = 0;
asm volatile("cpuid\n\t"
"rdtscp\n\t"
"mov %%edx, %0\n\t"
"mov %%eax, %1\n\t"
: "=r" (hi), "=r" (lo)
:: RDTSC_DIRTY);
unsigned long long that = (unsigned long long)((lo) |
(unsigned long long)(hi)<<32);
return that;
}
static inline unsigned long long stop_timer()
{
unsigned int hi = 0, lo = 0;
asm volatile("rdtscp\n\t"
"mov %%edx, %0\n\t"
"mov %%eax, %1\n\t"
"cpuid\n\t"
: "=r" (hi), "=r" (lo)
:: RDTSC_DIRTY);
unsigned long long that = (unsigned long long)((lo) |
(unsigned long long)(hi)<<32);
return that;
}
static inline double dtime(long long start, long long end)
{
return (double) (end - start) ;
}
TYPE BF[N] ;
long long start, end;
double benchtime;
void zero(){
int i, j, m ;
start=start_timer();
for (i=0;i<N;i++)
BF[i]=ZERO;
benchtime=dtime(start, stop_timer());
printf ("%g\n", benchtime);
}
void randtest(){
int i, j, m ;
srandom(100);
for (i=0;i<N;i++)
BF[i]=random();
int count=0;
start=start_timer();
for (i=0;i<N;i++){
if (BF[i]>RAND_MAX/2)
count++;
}
benchtime=dtime(start, stop_timer());
printf ("%g\n", benchtime);
}
void main()
{
#ifdef ZEROTEST
zero();
#else
randtest();
#endif
}
Вот результаты:
am @ Mandel: ~ / tmp / d $ cc -DZEROTEST time.c;для меня в 1 2 3 4 5 6 7 8 9 10;делать ./a.out;сделано
1.09084e + 07 1.14298e + 07 1.07197e + 07 1.26519e + 07 1.32742e + 07 1.37184e + 07 1.54689e + 07 1.36335e + 07 1.20818e + 07 1.12298e + 07
am @ Mandel: ~ / tmp / d $ cc -DZEROTEST -O time.c;для меня в 1 2 3 4 5 6 7 8 9 10;делать ./a.out;сделано
4.30112e + 06 4.37242e + 06 4.28102e + 06 4.51831e + 06 4.45952e + 06 5.77813e + 06 6.33686e + 06 5.44415e + 06 5.67434e + 06 5.90118e + 06
am @ Mandel: ~ / tmp / d $ cc time.c;для меня в 1 2 3 4 5 6 7 8 9 10;делать ./a.out;сделано
2.4763e + 07 2.77489e + 07 2.78568e + 07 3.3762e + 07 3.56298e + 07 3.66709e + 07 3.22833e + 07 2.68651e + 07 2.88412e + 07 2.92287e + 07
am @ Mandel: ~ / tmp / d $ cc -O time.c;для меня в 1 2 3 4 5 6 7 8 9 10;делать ./a.out;сделано
1.00543e + 06 1.15819e + 06 1.00544e + 06 2.74409e + 06 1.17561e + 06 1.40751e + 06 2.41898e + 06 1.65623e + 06 2.19502e + 06 1.59414e + 06
Как вы можете видеть, как правило, изменение времени составляет не менее 30%, но когда речь идет о предсказателях ветвлений, он может быть гораздо больше.И это происходит либо в оптимизированном, либо в неоптимизированном коде.
Вы не можете считать, что выполнение является чем-то детерминированным в современных архитектурах.Существуют вариации, связанные с выбором архитектурного дизайна, которые по крайней мере так же важны, как и эффекты ОСИ это очень сложно, когда речь идет о реальном времени.