【问题标题】:Why are values I obtain from clock() unsynchronized with real time?为什么我从 clock() 获得的值与实时不同步?
【发布时间】:2015-04-27 20:22:07
【问题描述】:

我在 C 中使用函数 clock() 来通过滴答声获取秒数,但是通过下面这个小测试程序,我发现我的处理器没有正确计算滴答声,因为秒数与实时,此外,我必须将结果乘以 100 才能得到更类似于秒的结果,但我认为这没有意义。在这个程序中,10s 几乎相当于现实生活中的 7s。有人可以帮我将clock() 函数变得更精确吗?

我正在使用带有内核 3.8.13-bone70、Debian 4.6.3-14 和 gcc 版本 4.6.3 的 Beaglebone Black rev C

提前致谢!

这是我的测试程序:

#include <stdio.h>
#include <time.h>
int main(){

    while(1)
    printf("\n%f", (double)100*clock()/CLOCKS_PER_SEC);

    return 0;
}

【问题讨论】:

  • 这是否意味着当你在命令提示符下输入日期命令时,显示的时间越来越远?
  • 顺便说一句:%f 是浮点数,而不是双精度数。 %lf 是双倍的
  • @user3629249:这是不正确的。 %f 对于floatdouble 都是正确的,因为float 参数被提升为double(因为printf 是一个可变参数函数)。 long double 的正确格式是 %Lf,而不是 %lf
  • @user3629249: 在printf 中两者都是(实际上只是double,但floats 在传递给可变参数函数时总是隐式转换为double)。
  • @user3629249:你完全错了。 printf%f 格式用于 double 类型的参数。 float 参数被提升为 double,所以 %f 也适用于它们。也许您正在考虑scanf,它有不同的规则(因为它需要指针参数并且它们没有被提升)?请参阅N1570,第 7.21.6.1 节,第 8 段(%f)和第 7 段(L 长度修饰符)。或者查看任何涵盖 C printf 函数的参考。

标签: c clock


【解决方案1】:

clock() 函数返回的结果预计不会与实时同步。它返回

实现对所使用的处理器时间的最佳近似 自实施定义时代开始以来的计划 仅与程序调用有关

如果您想要高精度指示真实(挂钟)时间,则需要使用一些特定于系统的函数,例如 gettimeofday()clock_gettime() -- 或者,如果您的实现支持它,标准的timespec_get函数,在C11中添加。

您的程序循环调用printf。我希望它花费大部分时间等待 I/O,让步给其他进程,以及 clock() 指示的 CPU 时间(当转换为秒时)以比实际时间慢得多。我怀疑你乘以 100 会影响你的结果; clock()/CLOCKS_PER_SEC 应该是 CPU 时间的正确指示。

【讨论】:

  • 然而,我希望如此紧密的无限循环所使用的 CPU 时间非常接近实时,因此值得进一步探索;-)
  • @SinanÜnür:问题中的循环包括对printf 的调用。我希望该进程将大部分时间花在等待 I/O 上,从而将 CPU 让给其他进程。我希望clock() 返回的值在转换为秒后会比实时慢得多。
  • 顺便说一句,C11 现在有独立于操作系统的功能timespec_get
  • @JensGustedt:已更新。
【解决方案2】:

注意Keith Thompson's answer,它为您指明了正确的方向。

但是,人们可能期望一个紧密的无限循环在给定的时间段内使用大部分 CPU(假设没有发生任何其他事情),因此在这个紧密的无限循环上花费的 CPU 时间与实际时间之间的任何严重偏差都可能是有趣的探索。为此,我编造了这个短节目:

#include <stdio.h>
#include <time.h>

int main(void) {
    time_t t0 = time(NULL);
    while(1) {
        printf("%f\r", ((double) clock())/CLOCKS_PER_SEC);
        fflush(stdout);
        if (difftime(time(NULL), t0) > 5.0) {
            break;
        }
    }

    return 0;
}

在 Windows 上,我得到:

C:\...\Temp> timethis clk.exe

TimeThis:命令行:clk.exe
TimeThis : 开始时间 : Mon Apr 27 17:00:34 2015

5.093000
TimeThis:命令行:clk.exe
TimeThis : 开始时间 : Mon Apr 27 17:00:34 2015
TimeThis : 结束时间 : Mon Apr 27 17:00:40 2015
TimeThis : 经过时间 : 00:00:05.172

在 *nix 上,您可以使用 time CLI 实用程序来测量时间。

时间对我来说已经足够接近了。

另请注意Zan's point about comms lags

【讨论】:

    【解决方案3】:

    Keith 的回答是最正确的,但是即使您确实将程序更改为使用实时,您的程序也存在另一个问题。

    你让它在一个没有睡眠的紧密循环中创建输出。如果您的输出设备有点慢,则显示的时间会随着缓冲的慢而关闭。

    例如,如果您在 9,600 波特串行控制台上运行此程序,它可能会延迟 30 秒之多。至少,这是我记得在很久以前我们仍然使用 9,600 波特控制台时观察到的延迟。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-20
      • 2013-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-15
      相关资源
      最近更新 更多