这取决于您观察到的变化。在现代计算机中,所有设计都是为了在统计上优化平均运行时间。但是许多架构特性是基于统计的,并且取决于初始条件可能导致非常不同的运行时间。这主要包括缓存和分支预测器。运行时有 20-30% 左右的变化是正常的。我们在裸机 OSless 系统上进行了实验,并且行为相同。
这是一个使用时间戳计数器(周期)测量时间的程序。可以测试两个简单的功能。一个只是零向量,第二个是对随机(但始终相同)向量的一组测试。
#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 ;对于 i 在 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 ;对于 i 在 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 ;对于 i 在 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 ;对于 i 在 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% 的时间变化是很常见的,但当涉及到分支预测器时,它可能会大得多。它发生在优化或未优化的代码中。
您不能认为执行在现代架构中是确定性的。由于架构设计选择的不同,至少与操作系统效果一样重要。就实时性而言,这是一个主要困难。