【问题标题】:why C clock() returns 0为什么C时钟()返回0
【发布时间】:2023-03-21 19:27:01
【问题描述】:

我有这样的东西:

clock_t start, end;
start=clock();

something_else();

end=clock();
printf("\nClock cycles are: %d - %d\n",start,end);

我总是得到输出“时钟周期为:0 - 0”

知道为什么会这样吗?

(仅提供一点细节,something_else() 函数使用蒙哥马利表示执行从左到右的幂运算,而且我不确定 something_else() 函数确实需要一些不可忽略的时间。)

这是在 Linux 上。 uname -a 的结果是:

Linux snowy.*****.ac.uk 2.6.32-71.el6.x86_64 #1 SMP Fri May 20 03:51:51 BST 2011 x86_64 x86_64 x86_64 GNU/Linux

【问题讨论】:

  • 你使用的是什么操作系统?
  • 我刚刚编辑了问题以添加此详细信息!
  • clock_t 可能不是int,所以%d 不合适。看到这个问题:stackoverflow.com/questions/1083142/….
  • @OliCharlesworth 我在互联网上看到很多例子,他们将其用作 int。不过,我会阅读您的链接,谢谢

标签: c linux clock


【解决方案1】:

clock 函数不测量 CPU 时钟周期。

C 说clock “将实现的最佳近似值返回给处理器 自实现定义的时代相关的开始以来程序使用的时间 仅限于程序调用。”

如果在两次连续的clock 调用之间,您的程序所花费的时间少于clock 函数的一个单位,您可以获得0

POSIX clockCLOCKS_PER_SEC 的单位定义为 1000000(单位为 1 微秒)。

http://pubs.opengroup.org/onlinepubs/009604499/functions/clock.html

要测量 x86/x64 中的时钟周期,您可以使用内联汇编来检索 CPU 时间戳计数器寄存器 rdtsc 的时钟计数。

【讨论】:

  • 你所说的时间戳计数器听起来很有趣。你能指出一个很好的来源吗?非常感谢
  • 另外,值得注意的是,虽然 clock() 是 C90 标准中的一个函数,但有些平台在技术上不支持 clock() 并且实现总是返回 -1。
【解决方案2】:

我猜原因是您的something_else() 消耗的时间太少,超过了clock() 的精度。结果我尝试调用clock() 两次,startend 都为零,但是当我在两者之间做一些耗时的事情时结果是合理的。

这是我的测试代码sn-p:

int main(void) {   
    clock_t start, end;
    start = clock();
    int c;
    for (int i = 0; i < 100; i++) {
        for (int j = 0; j < (1<<30); j++) {
            c++;
        }
    }
    end = clock();
    printf("start = %d, end = %d\n", start, end);
    return 0;
}

我电脑上的结果是:

start = 0, end = 27700000

另外,还有两个tips:

  1. 测试时,不要使用任何编译器优化。您可能认为您的 something_else() 很耗时,但编译器可能会忽略这些操作(尤其是循环),因为它认为它们毫无意义。
  2. 在您的平台上使用sizeof(clock_t) 查看clock_t 的大小。

【讨论】:

  • 我在我的系统上尝试了你的代码。运行需要几秒钟,但我仍然得到两个零。我还尝试将其打印为 printf("\nTime elapsed: %.2f\n",1.0*(end-start)/CLOCKS_PER_SEC);但我仍然得到零。时钟功能肯定有问题。有没有我需要设置的标志或你们知道的任何事情?
  • @eddyed: start 应该为零,因为它记录了程序启动后经过的时间,但end 不应该为零。据我所知,使用clock() 不需要特殊标志或任何其他技巧。顺便说一句,sizeof(clock_t) 在您的平台上的结果是什么?
  • -1 for don't optimize(不,我实际上并没有投反对票)。如果你想防止函数调用被优化出来,只需使用函数返回值,例如在程序结束时打印出来。
  • 通常不会对未优化的代码进行基准测试。 ;) 但说真的,给定的示例代码实际上并不能进行基准测试,原因有两个。不使用计算的任何结果或副作用,编译器可以删除它们。即使稍后使用 c,编译器也可以预先计算最终值,而不会生成任何循环。如果想测试 clock() 是否有效,只需调用 sleep(1)。
【解决方案3】:

好吧,你想要something_else() 花费的时间吗?试试这个:

#include <sys/time.h>
#include <stdio.h>  
#include <unistd.h>
int main(void) {
    struct timeval start, end;
    long mtime, secs, usecs;    

    gettimeofday(&start, NULL);
    something_else();
    gettimeofday(&end, NULL);
    secs  = end.tv_sec  - start.tv_sec;
    usecs = end.tv_usec - start.tv_usec;
    mtime = ((secs) * 1000 + usecs/1000.0) + 0.5;
    printf("Elapsed time: %ld millisecs\n", mtime);
    return 0;
}

【讨论】:

  • 不幸的是我需要时钟周期,而不是时间。
  • 我认为您将无法便携式测量时钟周期。我认为 C 或 POSIX 标准中没有任何相关内容。
  • @eddy ed,如果您想测量时钟周期,您需要使用逻辑分析仪、频率计数器或其他连接到硬件的硬件测量工具。
  • @mah:或者硬件计数器,例如现代 x86 上的 TSC。
  • @WindChaser 这是将浮点计算值四舍五入到最接近整数的正确方法。
【解决方案4】:

使用clock()测量时间的正确方法是:

printf("\nTime elapsed: %.2f\n",1.0*(end-start)/CLOCKS_PER_SEC);

这是因为 clock_t 不能保证是 int 或任何其他类型。

【讨论】:

  • OP 有兴趣知道为什么 startend 会变成 0?在这种情况下,浮点没有帮助
  • 我的意思是它们可能不是 int 类型,所以打印它们是没有意义的。使用它们的正确方法是减去两个数量并除以 CLOCKS_PER_SEC。几乎所有其他东西都是未定义的。我给出的代码可以正常显示经过的秒数。
【解决方案5】:

检查CLOCKS_PER_SECtime.h/clock.h 的值。例如,在我的系统上(Windows 7 上的 Dev Cpp)它只是 1000。所以就我的程序而言,每秒有 1000 个滴答声。您的 something_else 将在几微秒内执行。因此clock() 在函数调用前后都返回零。

在我的系统上,当我用这样一个耗时的例程替换你的 something_else

for (unsigned i=0xFFFFFFFF;i--;);

start=clock();

for (unsigned i=0xFFFFFFFF;i--;);

end=clock();

我明白了

时钟周期为:10236 - 20593

在其中一个 linux 机器上,我在 bits/time.h 中找到以下内容

/* ISO/IEC 9899:1990 7.12.1: <time.h>
   The macro `CLOCKS_PER_SEC' is the number per second of the value
   returned by the `clock' function. */
/* CAE XSH, Issue 4, Version 2: <time.h>
   The value of CLOCKS_PER_SEC is required to be 1 million on all
   XSI-conformant systems. */
#  define CLOCKS_PER_SEC  1000000l

所以在分析clock()的返回值之前一定要考虑这一点

【讨论】:

    【解决方案6】:

    我使用下面的小程序来调查挂钟时间和 CPU 时间。

    在我的测试系统上打印

    CLOCKS_PER_SEC 1000000

    CPU time usage resolution 看起来是 0.010000 seconds

    gettimeofday 更改为 9634 uSwhen CPU 时间更改为 0.010000

    gettimeofday 分辨率看起来是 1 us

    #include <stdio.h>
    #include <unistd.h>
    #include <sys/time.h>
    #include <ctime>
    
    
    int main(int argc, char** argv) {
    
        struct  timeval now; // wall clock times
        struct  timeval later;
    
        clock_t tNow = clock(); // clock measures CPU time of this Linux thread
        gettimeofday(&now, NULL); // wall clock time when CPU time first read
    
        clock_t tLater = tNow;
        while (tNow == tLater)
               tLater = clock(); // consume CPU time
    
        gettimeofday(&later, NULL); // wall clock time when CPU time has ticked
    
        printf("CLOCKS_PER_SEC %ld\n",CLOCKS_PER_SEC);
    
        double cpuRes = (double)(tLater - tNow)/CLOCKS_PER_SEC;
    
        printf("CPU time usage resolution looks to be %f seconds\n", cpuRes);
    
        unsigned long long nowUs = ((unsigned long long)now.tv_sec) * 1000000ULL;
        nowUs += (unsigned long long)now.tv_usec;
    
        unsigned long long laterUs = ((unsigned long long)later.tv_sec) * 1000000ULL;
        laterUs += (unsigned long long)later.tv_usec;
    
        printf("gettimeofday changed by %d uS when CPU time changed by %f seconds\n", (int)(laterUs - nowUs), cpuRes);
    
        // now measure resolution of gettimeofday
    
        gettimeofday(&now, NULL);
        later = now;
    
        while ((now.tv_sec  == later.tv_sec) && (now.tv_usec == later.tv_usec))
                gettimeofday(&later, NULL);
    
        nowUs = ((unsigned long long)now.tv_sec) * 1000000ULL;
        nowUs += (unsigned long long)now.tv_usec;
    
        laterUs = ((unsigned long long)later.tv_sec) * 1000000ULL;
        laterUs += (unsigned long long)later.tv_usec;
    
        printf("gettimeofday resolution looks to be %d us\n", (int)(laterUs - nowUs));
    
    }
    

    【讨论】:

      【解决方案7】:

      我在使用 C++ 和 g++ 编译器的 Red Hat Linux 上尝试使用向量计算泛型类和非泛型类之间的差异时遇到了同样的问题。 如果您的程序运行速度比单个时钟慢,那么 clock() 读数将始终为零 (0)。

      此代码将始终返回 0

      #include <iostream>
      #include <ctime>
      
      using namespace std;
      
      int main() {
      
          cout << clock() << endl;
      
          return 0;
      }
      

      当我添加一个索引高达一千万的 for 循环以减慢程序速度时,我从 clock() 得到一个数字 20000

      #include <iostream>
      #include <ctime>
      
      using namespace std;
      
      int main() {
      
          for (int i = 0; i < 10000000; i++) {}
          cout << clock() << endl;
      
          return 0;
      }
      

      当然,取决于您的机器的统计数据,结果会有所不同,我正在使用多处理器 Xeon CPU 和大量 RAM 运行此代码。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-21
        • 1970-01-01
        • 2015-06-21
        • 2022-01-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多