如何延长clock()的执行时间

时间:2017-07-25 20:42:45

标签: c linux

我的C程序可以运行超过3个小时。为了我的实验,我想计算程序所用的持续时间(即执行时间),直到完成为止。我在start = clock();的开头使用main(),最后我end = clock(),最后减去end - start获取执行时间。但是,正如here所述,clock_t clock(void)限制为72分钟。我怎样才能强制执行它来计算整个执行时间不仅仅是72分钟?

3 个答案:

答案 0 :(得分:2)

使用gettimeofday()https://linux.die.net/man/2/gettimeofday)。它在很长一段时间内提供微秒分辨率。记录开始时间和结束时间并计算差异。

答案 1 :(得分:2)

time()函数在C89,C99,C11中指定。它具有第二个分辨率,通常超过30位秒。它可能是最便携的解决方案。事实上,直到今天我才听说过clock()。即使你需要高分辨率,计数滴答也很少你想要的。

如果您不需要便携方式来测量CPU /执行时间,请使用procfsproc/self/stat的{​​{1}}字段和stime应该就是您所需要的。

答案 2 :(得分:2)

所有POSIXy系统(包括Linux)的标准是clock_gettime() POSIX.1函数。

考虑以下示例:

#define _POSIX_C_SOURCE 200809L
#include <stdlib.h>
#include <time.h>

/* Clock used by wall_start()/wall_elapsed() */
#ifdef CLOCK_MONOTONIC
#define  WALL_CLOCK_ID  CLOCK_MONOTONIC
#else
#define  WALL_CLOCK_ID  CLOCK_REALTIME
#endif

static struct timespec  wall_started = { 0 };

static inline void wall_start(void)
{
    if (clock_gettime(WALL_CLOCK_ID, &wall_started)) {
        wall_started.tv_sec = 0;
        wall_started.tv_nsec = 0;
    }
}

static inline void wall_elapsed(void)
{
    struct timespec  t;
    if (!clock_gettime(WALL_CLOCK_ID, &t))
        return (double)(t.tv_sec - wall_started.tv_sec)
             + (double)(t.tv_nsec - wall_started.tv_nsec) / 1000000000.0;
    else
        return -1.0;
}

/* Return the number of seconds of CPU time
   used by this process (includes all threads)
*/
static inline double cpu_elapsed(void)
{
    struct timespec  t;

    if (!clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t))
        return (double)t.tv_sec
             + (double)t.tv_nsec / 1000000000.0;

    return -1.0;
}

如果您想以天,小时,分钟和秒显示时间,您还需要一个简单的功能将(浮点)秒分为几天,几小时和几分钟。

这是一个实现,它指向int的天,小时和分钟;如果你不想将其拆分,你可以使用NULL。该函数返回剩余的秒数:

static inline double split_seconds(double  secs,
                                   int    *days,
                                   int    *hours,
                                   int    *minutes)
{
    /* We split the absolute number of seconds, only. */
    if (secs < 0.0)
        secs = 0.0;

    if (days) {
        const int  ndays = (int)(secs / 86400.0);
        secs -= (double)ndays * 86400.0;
        *days = ndays;
    }

    if (hours) {
        const int  nhours = (int)(secs / 3600.0);
        secs -= (double)nhours * 3600.0;
        *hours = nhours;
    }

    if (minutes) {
        const int  nminutes = (int)(secs / 60.0);
        secs -= (double)nminutes * 60.0;
        *minutes = nminutes;
    }

    return secs;
}

例如,调用split_seconds(3661.25, NULL, &h, NULL)会使61.25返回h == 1。致电split_seconds(3661.25, &d, &h, &m)返回1.25d == 0h == 1m == 1,对应0天,1小时,1分钟和1.25秒。

CLOCK_REALTIME时钟是POSIXy系统中的标准挂钟,但它受NTP(网络时间协议)更改的影响,系统管理员可以直接设置它。但是,它不受夏令时或任何与时区相关的影响,因为它是UTC,而不是当地时间。

CLOCK_MONOTONIC时钟类似于CLOCK_REALTIME,但其时代未知(可能设置为机器上次启动时的某个时间),并且不受NTP时间跳转的影响(但受NTP的小增量更改影响,以使计算机时钟与网络时间源保持同步),并且不受系统管理员对系统时间更改的影响。

如果可用,CLOCK_MONOTONIC被认为比CLOCK_REALTIME更适合衡量过去的实际时间; CLOCK_REALTIME更适合与绝对现实世界时间进行比较的情况,或者检查特定日期/时间是否已经过去。

如果您打算将时间戳存储到例如一个文件,你必须使用CLOCK_REALTIME而不是CLOCK_MONOTONIC,因为后者只在同一台机器上有意义,直到下一次启动。

使用CLOCK_REALTIME时,请记住它是UTC格式,用户通常会在当地时间指定时间和日期;您可能希望使用strptime() POSIX.1函数来解析文本(在Linux中使用#define _XOPEN_SOURCE),并使用mktime()生成可以存储到{time_t的{​​{1}} 1}} tv_sec结构的成员。