如何测量cpu时间和挂钟时间?

时间:2013-07-06 10:56:59

标签: c performance time cpu

我看到很多关于此的主题,即使是在stackoverflow上,例如:

How can I measure CPU time and wall clock time on both Linux/Windows?

我想测量cpu和wall时间。尽管在我发布的主题中回答问题的人建议使用gettimeofday来衡量一个时间,但我认为最好使用clock_gettime。所以,我写了下面的代码(它没关系,它是否真的测量了一个时间,而不是cpu时间?我问,因为我找到了一个网页:http://nadeausoftware.com/articles/2012/03/c_c_tip_how_measure_cpu_time_benchmarking#clockgettme其中它表示clock_gettime测量cpu时间......)真相是什么,我应该用哪一个来衡量一个时间?

另一个问题是关于cpu时间。我找到了clock很好的答案,所以我也为它写了一个示例代码。但它不是我真正想要的,因为我的代码它显示了0秒的CPU时间。是否可以更准确地测量cpu时间(以秒为单位)?感谢您的帮助(目前我只对Linux解决方案感兴趣)。

继承我的代码:

#include <time.h>
#include <stdio.h>      /* printf */
#include <math.h>       /* sqrt */
#include <stdlib.h>

int main()
{
    int i;
    double sum;

    // measure elapsed wall time
    struct timespec now, tmstart;
    clock_gettime(CLOCK_REALTIME, &tmstart);
    for(i=0; i<1024; i++){
        sum += log((double)i);
    }
    clock_gettime(CLOCK_REALTIME, &now);
    double seconds = (double)((now.tv_sec+now.tv_nsec*1e-9) - (double)(tmstart.tv_sec+tmstart.tv_nsec*1e-9));
    printf("wall time %fs\n", seconds);

    // measure cpu time
    double start = (double)clock() /(double) CLOCKS_PER_SEC;
    for(i=0; i<1024; i++){
        sum += log((double)i);
    }
    double end = (double)clock() / (double) CLOCKS_PER_SEC;
    printf("cpu time %fs\n", end - start);

    return 0;
}

像这样编译:

  

gcc test.c -o test -lrt -lm

它告诉我:

wall time 0.000424s
cpu time 0.000000s

我知道我可以进行更多的迭代,但这不是重点;)

重要提示:

printf("CLOCKS_PER_SEC is %ld\n", CLOCKS_PER_SEC);

显示

CLOCKS_PER_SEC is 1000000

1 个答案:

答案 0 :(得分:6)

根据clock上的手册页,它说

  

POSIX要求CLOCKS_PER_SEC等于1000000,与实际分辨率无关。

当增加计算机上的迭代次数时,测量的cpu-time开始显示在100000次迭代上。从返回的数字来看,分辨率实际上是10毫秒。

请注意,在优化代码时,整个循环可能会消失,因为sum是一个死值。也没有什么可以阻止编译器在循环中移动clock语句,因为它们之间没有真正的依赖关系。

让我详细说明代码性能的微观测量。测量性能的天真和诱人的方法确实是通过添加clock语句来完成的。但是,由于时间不是C中的概念或副作用,编译器通常可以随意移动这些clock个调用。为了解决这个问题,很容易让这些clock调用产生副作用,例如让它访问volatile个变量。但是,这仍然不能阻止编译器在调用上移动高度无副作用的代码。想想访问常规局部变量的例子。但更糟糕的是,通过使clock调用对编译器看起来非常可怕,您实际上会对任何优化产生负面影响。因此,仅仅衡量绩效会以负面和不合需要的方式影响绩效。

如果你使用了某个人已经提到的分析,你可以对优化代码的性能进行非常好的评估,尽管总体时间当然会增加。

衡量性能的另一个好方法是让编译器报告一些代码将采用的周期数。对于许多体系结构,编译器对此有非常准确的估计。然而,最值得注意的是奔腾架构并不是因为硬件执行了大量难以预测的调度。

虽然这不是常规练习,但我认为编译器应该支持标记要测量的函数的pragma。然后,编译器可以在函数的序言和结尾中包括高精度非侵入式测量点,并禁止任何内联函数。根据架构,它可以选择高精度时钟来测量时间,最好是在操作系统的支持下,只测量当前过程的时间。