【问题标题】:clock() returns 0时钟()返回 0
【发布时间】:2015-03-04 00:27:22
【问题描述】:

当我在下面运行我的代码时,我得到了一个值 0,有几次我确实得到了 intAddition 的值。我尝试了很多我在网上找到的建议,但还没有成功。我的同学向我展示了他的做法,这与我的非常相似。他从他的程序中获得了 1 到 3 的小值。

感谢您的帮助!

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

clock_t start, end;

void intAddition(int a, int b){
    start = clock();
    a + b;
    end = clock();  
    printf("CPU cycles to execute integer addition operation: %d\n", end-start);
}

void intMult(int a, int b){
    start = clock();
    a * b;
    end = clock();
    printf("CPU cycles to execute integer multiplication operation: %d\n", end-start);
}

void floatAddition(float a, float b){
    start = clock();
    a + b;
    end = clock();
    printf("CPU cycles to execute float addition operation: %d\n", end-start);
}

void floatMult(float a, float b){
    start = clock();
    a * b;
    end = clock();
    printf("CPU cycles to execute float multiplication operation: %d\n", end-start);
}

int main()
{
    int a,b;
    float c,d;

    a = 3, b = 6;
    c = 3.7534, d = 6.85464;

    intAddition(a,b);
    intMult(a,b);
    floatAddition(c,d);
    floatMult(c,d);

    return 0;
}

【问题讨论】:

  • clock 以相当粗略的方式返回 CPU 时间(通常以 1-100 毫秒为增量)。不是 CPU 的时钟周期。所以,是的,我希望每次都为零。
  • 你应该循环操作被计时很多次。但是注意,如果你只写a+b,编译器可能会优化掉它,因为它没有任何效果。
  • 我刚刚尝试循环操作,但我仍然得到 0。
  • @Ugluk 多少次迭代?从100万开始。至少。要获得真实的 CPU 周期数,您需要类似 rdtsc,而不是 clock
  • 不要假设clock_t 值可以用%d 打印。 clock_t 是实现定义的算术类型。您可以将其转换为已知类型,例如printf("%ld\n", (long)(end - start));

标签: c++ clock


【解决方案1】:

clock() 返回的值是clock_t 类型(实现定义的算术类型)。它代表“实现对处理器的最佳近似 自实现定义的时代相关的开始以来程序使用的时间 仅用于程序调用”(N15707.27.2.1)。

给定一个clock_t 值,您可以通过将它乘以CLOCKS_PER_SEC(在&lt;time.h&gt; 中定义的实现定义的宏)来确定它所代表的秒数。 POSIX 要求CLOCKS_PER_SEC 为一百万,但在不同的系统上可能有不同的值。

特别注意,CLOCKS_PER_SEC 的值不一定clock() 函数的实际精度相对应。

根据实现,如果 CPU 时间消耗量小于 clock() 函数的精度,则对 clock() 的两次连续调用可能会返回相同的值。在我测试的一个系统上,clock() 函数的分辨率为 0.01 秒; CPU 可以在这段时间内执行很多 条指令。

这是一个测试程序:

#include <stdio.h>
#include <time.h>
#include <limits.h>
int main(void) {
    long count = 0;
    clock_t c0 = clock(), c1;
    while ((c1 = clock()) == c0) {
        count ++;
    }
    printf("c0 = %ld, c1 = %ld, count = %ld\n",
           (long)c0, (long)c1, count);
    printf("clock_t is a %d-bit ", (int)sizeof (clock_t) * CHAR_BIT);
    if ((clock_t)-1 > (clock_t)0) {
        puts("unsigned integer type");
    }
    else if ((clock_t)1 / 2 == 0) {
        puts("signed integer type");
    }
    else {
        puts("floating-point type");
    }
    printf("CLOCKS_PER_SEC = %ld\n", (long)CLOCKS_PER_SEC);
    return 0;
}

在一个系统(Linux x86_64)上,输出为:

c0 = 831, c1 = 833, count = 0
clock_t is a 64-bit signed integer type
CLOCKS_PER_SEC = 1000000

显然,在那个系统上,clock() 函数的实际分辨率是一到两微秒,两次连续调用 clock() 会返回不同的值。

在另一个系统 (Solaris SPARC) 上,输出为:

c0 = 0, c1 = 10000, count = 10447
clock_t is a 32-bit signed integer type
CLOCKS_PER_SEC = 1000000

在那个系统上,clock() 函数的分辨率是 0.01 秒(10,000 微秒),clock() 返回的值在几千次迭代中都没有变化。

(至少)还有一件事需要注意。在clock_t 为 32 位的系统上,使用CLOCKS_PER_SEC == 1000000,该值可以在大约 72 分钟的 CPU 时间后回绕,这对于长时间运行的程序可能很重要。有关详细信息,请参阅系统文档。

【讨论】:

    【解决方案2】:

    在某些编译器中,clock() 以毫秒为单位测量时间。此外,编译器对于简单测试来说太聪明了,它可能会跳过所有内容,因为这些操作的结果没有被使用。

    例如,这个循环可能需要不到 1 毫秒(除非调试器打开或优化关闭)

    int R = 1;
    int a = 2;
    int b = 3;
    start = clock();
    for( int i = 0; i < 10000000; i++ ) 
        R = a * b;
    printf( "time passed: %ld\n", clock() - start );
    

    R 始终是相同的数字 (6),甚至没有使用 R。编译器可能会跳过所有计算。您必须在最后打印 R 或做其他事情来欺骗编译器以配合测试。

    【讨论】:

    • 不一定以毫秒为单位。转换因子是CLOCKS_PER_SEC(在 POSIX 系统上要求为一百万,但在非 POSIX 系统上可能不同。您的printf 假设(如问题中的代码那样)clock_t 是兼容的int,这是无法保证的。有关更多信息,请参阅我的答案。
    猜你喜欢
    • 2019-08-21
    • 2023-03-21
    • 2012-08-12
    • 1970-01-01
    • 2012-01-26
    • 1970-01-01
    • 2015-06-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多