【问题标题】:Why the execution time of the same code on the same computer could be different?为什么相同代码在同一台计算机上的执行时间可能不同?
【发布时间】:2019-01-19 21:58:13
【问题描述】:

我是 C 编程的新手,我编写了代码并希望获得它的运行时。这就是我所做的。每次我运行我的代码时,我都会得到不同的运行时间值。这样对吗?还是我的代码有问题?

int main(int argc, char *argv[])
{
    time_t start,end;
    start=clock();
    // this part is some operation

    end=clock();
    int running_time=end-start;
    printf("Time taken: %d",running_time);
    return 0;
}

【问题讨论】:

  • 不,你的代码没有任何“错误”(除了它不完整:你留下了 fw 行,所以它不会如图所示编译)。只是应用程序的“启动时间”是“不确定的”。将缓冲的“printf()”文本 I/O 显示到屏幕的延迟也是如此。仅这些因素就可以解释您看到的任何差异。
  • 只要您对仅显示“您未显示的代码使用的处理器时间的近似值”感兴趣,您显示的检测代码本质上没有任何问题。我建议您分析所有代码。
  • 建议:阅读此Programming Optimization, Paul Hsieh。它会给你一些关于“性能”的好主意,以及如何编写更有用和更现实的“基准”的建议。
  • Windows 和 Linux 操作系统不提供任何时间保证。此外,任何给你时间的函数都有一个分辨率,所以clock() 为一个时间段返回相同的值,为下一个时间段返回另一个值(大于 +1),依此类推。
  • 请注意clock() 函数返回clock_t 值而不是time_t 值。由clock() 测量的值报告为每经过一秒计数的 CLOCKS_PER_SEC。它还测量使用的处理器时间量,这与经过的(挂钟)时间不同。请注意您对结果的解释。 (尽管如此,您所做的是一种测量时间的方法,所花费的时间可能会有所不同,具体取决于主要与系统上同时运行的其他内容相关的各种因素。)

标签: c


【解决方案1】:

代码没有错。 它只是了解您的程序执行的操作系统调度程序,它一直在变化。

【讨论】:

    【解决方案2】:

    运行时间变化是很正常的,因为您的计算机可能正在运行许多东西(包括您的操作系统),而不仅仅是那段代码,这会影响时钟速度。

    在处理消耗非常稳定的计算机上,运行时间应该保持相似

    您的代码没有任何问题。

    【讨论】:

      【解决方案3】:

      这取决于您观察到的变化。在现代计算机中,所有设计都是为了在统计上优化平均运行时间。但是许多架构特性是基于统计的,并且取决于初始条件可能导致非常不同的运行时间。这主要包括缓存和分支预测器。运行时有 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% 的时间变化是很常见的,但当涉及到分支预测器时,它可能会大得多。它发生在优化或未优化的代码中。

      您不能认为执行在现代架构中是确定性的。由于架构设计选择的不同,至少与操作系统效果一样重要。就实时性而言,这是一个主要困难。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-07-11
        • 2020-06-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多