如何在C语言中测量时间?

57

我想找出某段代码执行的时间长短(大概)。就像这样:

startStopwatch();
// do some calculations
stopStopwatch();
printf("%lf", timeMesuredInSeconds);

怎么做?


@Pmod 你所说的平台是什么意思?我的操作系统是Windows。 - snakile
1
你想要达到什么分辨率,又能容忍多少累积开销? - Noah Watkins
@Noah,我可以容忍一毫秒的误差。 - snakile
一毫秒是很长的时间。几乎任何软件时钟都足够好用。 - Noah Watkins
对于Unix系统,请参见<time.h>中的clock()精度 - Jonathan Leffler
8个回答

87

你可以在time.h中使用clock方法。

示例:

clock_t start = clock();
/*Do something*/
clock_t end = clock();
float seconds = (float)(end - start) / CLOCKS_PER_SEC;

@torak 是的,我认为你是对的,不过我还没有测试过。 - KLee1
20
注意,clock()测量的是CPU时间,而不是挂钟时间(这可能是您需要的,也可能不是)。 - caf
4
在Linux中,当“while true”时,clock()函数实际上计算的是墙上的时间。但在Windows上,它计算的是挂钟时间:http://msdn.microsoft.com/en-us/library/4e2ess30.aspx - undefined
1
@undefined:不仅仅是Linux,实际上C标准规定了“clock函数确定处理器使用的时间”。我想在Windows上,你可以简单地说实现对处理器使用时间的最佳近似是墙钟时间使用。 - caf
2
注意:对于任何困惑的人,CLOCKS_PER_SEC不是您CPU的时钟频率。 - JAAAY
显示剩余2条评论

26

你可以使用time.h库,具体而言是timedifftime函数:

/* difftime example */
#include <stdio.h>
#include <time.h>

int main ()
{
  time_t start,end;
  double dif;

  time (&start);
  // Do some calculation.
  time (&end);
  dif = difftime (end,start);
  printf ("Your calculations took %.2lf seconds to run.\n", dif );

  return 0;
}

(示例改编自上述difftime网页。)

请注意,此方法只能提供秒级精度 - time_t记录了自UNIX纪元(1970年1月1日)以来的秒数。


1
这只提供了秒精度。而且你的示例实际上没有使用 <ctime.h> - Dummy00001
抱歉,“c”是一个打字错误 - ctime库在time.h中定义。是的,它只提供秒级精度。考虑到发布者说“大约”,我认为这已经足够了。如果您愿意,我将编辑我的答案以包括它只会给出秒级别的精度这一事实。 - Stephen

7

有时需要测量天文时间而不是CPU时间(尤其适用于Linux):

#include <time.h>

double what_time_is_it()
{
    struct timespec now;
    clock_gettime(CLOCK_REALTIME, &now);
    return now.tv_sec + now.tv_nsec*1e-9;
}

int main() {
    double time = what_time_is_it();
    printf("time taken %.6lf\n", what_time_is_it() - time);
    return 0;
}

它比clock()提供了更好的精度!但值得一提的是,仅包含time.h对我来说是不够的。我必须使用-lrt链接可执行文件。 - Alexander Samoylov

5

标准C库提供time函数,如果您只需要比较秒数,则此函数很有用。但是,如果需要毫秒级精度,则最便携的方法是调用timespec_get函数。如果系统支持,它可以告诉时间精度高达纳秒。不过,调用它需要更多的努力,因为它涉及一个结构体。下面是一个将结构体转换为简单的64位整数的函数。

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

int64_t millis()
{
    struct timespec now;
    timespec_get(&now, TIME_UTC);
    return ((int64_t) now.tv_sec) * 1000 + ((int64_t) now.tv_nsec) / 1000000;
}

int main(void)
{
    printf("Unix timestamp with millisecond precision: %" PRId64 "\n", millis());
}

clock 不同,此函数返回 Unix 时间戳,因此它将正确地计算阻塞函数(如 sleep)中花费的时间。这是进行基准测试和实现考虑运行时间延迟的有用属性。

3

GetTickCount().

#include <windows.h>
void MeasureIt()
{
    DWORD dwStartTime = GetTickCount();
    DWORD dwElapsed;

    DoSomethingThatYouWantToTime();

    dwElapsed = GetTickCount() - dwStartTime;

    printf("It took %d.%3d seconds to complete\n", dwElapsed/1000, dwElapsed - dwElapsed/1000);
}

2
为了完整起见,有一个比 GetTickCount() 或者 clock() 更精确的时钟计数器,它可以给你一个只有32位结果的快速溢出。这就是 QueryPerformanceCounter()QueryPerformanceFrequency() 获取时钟频率,这是两个计数器差异的除数。类似于 <time.h> 中的 CLOCKS_PER_SEC
#include <stdio.h>
#include <windows.h>

int main()
    {
    LARGE_INTEGER tu_freq, tu_start, tu_end;
    __int64 t_ns;

    QueryPerformanceFrequency(&tu_freq);
    QueryPerformanceCounter(&tu_start);
    /* do your stuff */
    QueryPerformanceCounter(&tu_end);

    t_ns = 1000000000ULL * (tu_end.QuadPart - tu_start.QuadPart) / tu_freq.QuadPart;
    printf("dt = %g[s]; (%llu)[ns]\n", t_ns/(double)1e+9, t_ns);

    return 0;
    }

1
我会使用 Windows API 的 QueryPerformanceCounterQueryPerformanceFrequency 函数。在代码块之前和之后调用前者,并减去(当前值 - 旧值)以获取两个实例之间的“滴答数”。将此除以后者函数获得的值,即可得到持续时间(秒)。

0
如果你不需要太高的分辨率,可以使用 GetTickCount():http://msdn.microsoft.com/en-us/library/ms724408(VS.85).aspx (如果不是用于简单的自我诊断,则需要注意此数字可能会环绕,因此你需要进行一些算术处理来解决这个问题)。
QueryPerformanceCounter 也是另一个合理的选择。(在MSDN上有描述)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接