奇怪的clock()行为

时间:2016-06-16 12:05:37

标签: c time clock

有人可以解释这个clock()(time_h)行为:

clock_t start, stop;
long i;
double t = 0.;
for(i = 0; i < 10e7; i++){
    start = clock();
    //nothing
    stop = clock();
    t = t + (double)(stop - start) / CLOCKS_PER_SEC;
}
printf("t: %fs\n", t);

输出:

t: 12.883712s

我认为原因可能是clock()错误导致的小t值的累积。有办法解决这个问题吗?

更新:只是为了解释“现实世界”的情况,因为有很多建议。 //没有是一段代码,其时间间隔非常小(可能是纳米级),而不是一个循环,其中很少有很难测量。

3 个答案:

答案 0 :(得分:3)

您获得的答案是合理的,因为编译器无法优化clock()来电,而且我看不到对clock()的来电特别便宜

但是你的测量在数值上是不准确的 - 我认为你的方法低估了总数。尝试

clock_t start, stop;
clock_t total = 0;
for (long/*don't overflow a 16 bit int*/ i = 0; i < 10e7; i++){
    start = clock();
    stop = clock();
    total += stop - start
}
double t = 1.0 * total / CLOCKS_PER_SEC;
printf("t: %fs\n", t);

代替。也就是说,最后进行划分。

在某种意义上,您可以使用

校准开销
start = clock();
/*ToDo - the real code*/
stop = clock();
control = clock();
/*Time is (stop - start) - (control - stop)*/

答案 1 :(得分:0)

考虑以下对您的计划的修改:

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

int main( int argc, char *argv[]) {
  clock_t start, stop;
  int i;
  double t = 0.;
  int n = atoi(argv[1]);
  int cnt = 0;
  for(i = 0; i < n; i++){
    start = clock();
    //nothing
    stop = clock();
    if ( start != stop) {
      printf( "%d %d\n", start, stop);
      cnt++;
    }
    t = t + (double)(stop - start) / CLOCKS_PER_SEC;
  }
  printf("t: %gs %g %d\n", t, t/n, cnt);
  return 0;
}

两次运行的输出

$ ./a.out 1000000
30000 40000
70000 80000
90000 100000
110000 120000
170000 180000
180000 190000
220000 230000
230000 240000
240000 250000
250000 260000
260000 270000
270000 280000
t: 0.12s 1.2e-07 12

$ ./a.out 100000
t: 0s 0 0

这表明您获得了非零值,因为当您运行循环足够多次时startend值不同,因为偶尔会在clock时间之前运行即将更改,因此第二个调用返回不同的值。发生这种情况时,t会增加。

答案 2 :(得分:0)

您无法使用clock()来衡量非常短的时间跨度(或者,除非您使用实时操作系统和非常小心,否则使用任何其他方法)。

添加大量小测量值并不是一个好主意,因为粒度问题可能会累积。测量大循环并除以迭代次数要好得多:

clock_t start, stop;
long i, num_iter = 1e8;
start = clock();
for(i = 0; i < num_iter; i++){
    //whatever
}
stop = clock();
t = (double)(stop - start) / num_iter / CLOCKS_PER_SEC;
printf("t: %fs\n", t);

如果您觉得//whatever的时间太短,只需增加迭代次数!

但是如果循环代码有两个部分:一个用于准备数据,另一个是要测量的真实代码? ......如果没有准备阶段,你就无法运行真正的代码。或者简单地说,如果我想测量的代码非常短并且循环开销太大,该怎么办?

然后,一种方法是运行测量两次,其中一次绕过待测量的代码,然后计算差异:

clock_t start, time1, time2;
long i, num_iter = 1e8;
double t;

start = clock();
for(i = 0; i < num_iter; i++){
    prepare_algoritm();
}
time1 = clock() - start;

start = clock();
for(i = 0; i < num_iter; i++){
    prepare_algoritm();
    run_algorith();
}
time2 = clock() - start;

t = (double)(time2 - time1) / num_iter / CLOCKS_PER_SEC; 
printf("run_algorithm time: %fs\n", t);