为什么 C clock() 返回 0

2024-11-11 08:27:00
admin
原创
20
摘要:问题描述:我有类似这样的事情:clock_t start, end; start=clock(); something_else(); end=clock(); printf(" Clock cycles are: %d - %d ",start,end); 我总是得到输出“时钟周期为...

问题描述:

我有类似这样的事情:

clock_t start, end;
start=clock();

something_else();

end=clock();
printf("
Clock cycles are: %d - %d
",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


解决方案 1:

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

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

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

POSIXclock将单位定义为CLOCKS_PER_SEC1000000(单位为 1 微秒)。

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

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

解决方案 2:

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

这是我的测试代码片段:

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
", start, end);
    return 0;
}

我的电脑上的结果是:

start = 0, end = 27700000

另外,还有两个建议:

  1. 测试时,不要使用任何编译器优化。你可能认为你的something_else()优化很耗时,但编译器可能会忽略这些操作(尤其是循环),因为它认为它们毫无意义。

  2. 在您的平台上使用sizeof(clock_t)来查看的大小clock_t

解决方案 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
", mtime);
    return 0;
}

解决方案 4:

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

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

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

解决方案 5:

CLOCKS_PER_SEC检查中的值time.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 resolutio看起来0.010000 seconds

gettimeofday 已更改9634 uSCPU 时间已更改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
",CLOCKS_PER_SEC);

    double cpuRes = (double)(tLater - tNow)/CLOCKS_PER_SEC;

    printf("CPU time usage resolution looks to be %f seconds
", 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
", (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
", (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 循环来减慢程序速度时,我得到了一个数字 20000 作为 clock() 的结果

#include <iostream>
#include <ctime>

using namespace std;

int main() {

    for (int i = 0; i < 10000000; i++) {}
    cout << clock() << endl;

    return 0;
}

当然,根据您的盒子的统计数据,结果会有所不同,我正在使用多处理器 Xeon CPU 以及大量 RAM 运行此代码。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用