【问题标题】:How to measure cpu time and wall clock time?如何测量cpu时间和挂钟时间?
【发布时间】:2013-07-04 08:19:09
【问题描述】:

我看到了很多关于这个的话题,甚至在stackoverflow上,例如:

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

我想同时测量 CPU 和挂墙时间。尽管在我发布的主题中回答问题的人建议使用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

【问题讨论】:

  • @sashkello:我希望我可以,但我需要自己做 :)
  • 如果您不将clock() 函数的结果除以CLOCKS_PER_SEC,您的分辨率可能会超过一秒,hrm?
  • @mah:那它会给我一个正确的 cpu 时间吗?这里说,我需要划分它:chemie.fu-berlin.de/chemnet/use/info/libc/libc_17.html
  • @BrianBrown 当您将一个数字除以另一个数字时会发生什么,它会变得更准确还是更少?更简单的问题:它变大还是变小?是的,您链接的网站在其示例中进行了划分,但它取决于 来理解推理,毫无疑问,无论它有什么原因都不是为了提高分辨率。至于“确定正确的 cpu 时间”——如果 clock() 返回正确的 cpu 时间,那么当然不要修改它。永远不要输入你在随机位置找到的代码,而不考虑它首先实际做了什么。
  • “真相是什么,我应该用哪一个来测量墙上的时间?” - 事实上,有 许多 种不同的方法来测量挂墙时间。有些比其他的更精确。有些比其他的更便携。您可以选择并使用适合您的任何东西。我对您链接的问题的回答使用gettimeofday(),因为这是对我来说足够好的第一件事。

标签: c performance time cpu


【解决方案1】:

根据我在clock 上的手册页,它说

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

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

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

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

如果您使用分析,正如某人已经提到的那样,您甚至可以对优化代码的性能进行很好的评估,尽管总时间当然会增加。

另一个衡量性能的好方法是要求编译器报告某些代码将花费的周期数。对于很多架构,编译器对此都有非常准确的估计。但最值得注意的是,对于 Pentium 架构,它不会,因为硬件会执行大量难以预测的调度。

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

【讨论】:

  • 根据cplusplus.com/reference/ctime/clock 我需要将clocks 的差异除以CLOCKS_PER_SEC,对吗?但你的意思是,只有 100000 次或更多次迭代,我才能在几秒钟内看到结果?
  • 我的意思是,即使CLOCKS_PER_SEC 是 1000000,clock 函数在我的系统上也会返回 10000 的倍数,我猜在大多数 Linux 系统上。因此,要获得合理的测量结果,您需要运行应用程序至少十分之几秒。但实际上我的观点是,很难对代码进行这样的微观测量,因为编译器不知道你想要测量的东西,并且可以以意想不到的方式安排你的测量点。
  • @BrianBrown 我已经添加了一些关于微观测量的详细说明。
猜你喜欢
  • 2013-06-30
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
  • 2019-11-02
  • 1970-01-01
  • 2013-12-25
  • 1970-01-01
  • 2017-11-02
相关资源
最近更新 更多