提问者:小点点

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


我看到了很多关于这方面的话题,甚至在stackoverflow上也是如此,例如:

如何在Linux/Windows上测量CPU时间和挂钟时间?

我想同时测量cpu和墙壁时间。虽然在我发布的主题中回答一个问题的人建议使用来测量墙时间,但我读到最好使用。因此,我编写了下面的代码(它是不是真的测量了墙壁时间,而不是cpu时间?我在问,因为我发现了一个网页:http://nadeausoftware.com/articles/2012/03/c_c_tip_how_measure_cpu_time_benchmarking/clockgettme,其中说测量了cpu时间。。。)真相是什么?我应该用哪一个来衡量墙壁时间?

另一个问题是关于cpu时间的。我发现非常适合它,所以我也为它编写了一个示例代码。但这并不是我真正想要的,对于我的代码来说,它显示了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测试。C-O测试-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个答案

匿名用户

根据我的手册页,它说

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

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

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

让我详细介绍一下代码性能的微观度量。度量性能的天真而诱人的方法确实是像您所做的那样添加语句。然而,由于时间在C语言中不是一个概念或副作用,编译器通常可以随意移动这些调用。为了解决这个问题,很容易让这样的调用产生副作用,例如让它访问变量。然而,这仍然不禁止编译器在调用中移动具有高附带效应的自由代码。例如,考虑访问常规局部变量。但更糟糕的是,如果使调用在编译器看来非常可怕,那么实际上将对任何优化产生负面影响。因此,仅仅衡量绩效会以负面和不可取的方式影响绩效。

如果您使用分析,正如已经有人提到的,您可以得到一个相当好的性能评估,即使是优化的代码,尽管总的时间当然增加了。

另一种衡量性能的好方法是要求编译器报告某些代码将花费的周期数。对于许多体系结构,编译器对此有非常精确的估计。然而,最值得注意的是,对于Pentium架构来说,它并不是这样,因为硬件需要进行大量的调度,这是很难预测的。

虽然这不是一个长期的实践,但我认为编译器应该支持标记要度量的函数的。然后,编译器可以在函数的序言和尾声中包含高精度,非侵入性的测量点,并禁止函数的任何内联。根据体系结构,它可以选择高精度时钟来测量时间,最好是在操作系统的支持下仅测量当前进程的时间。