clock_gettime和CLOCK_PROCESS_CPUTIME_ID错误的数字

时间:2012-08-10 11:40:23

标签: c precision clock timing gettime

我使用的是64位Ubuntu 12.04系统,并尝试使用以下代码:

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


int
main(void)
{
  struct timespec user1,user2;
  struct timespec sys1,sys2;
  double user_elapsed;
  double sys_elapsed;

  clock_gettime(CLOCK_REALTIME, &user1);
  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &sys1);
  sleep(10);
  clock_gettime(CLOCK_REALTIME, &user2);
  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &sys2);
  user_elapsed = user2.tv_sec + user2.tv_nsec/1E9;
  user_elapsed -= user1.tv_sec + user1.tv_nsec/1E9;
  printf("CLOCK_REALTIME: %f\n", user_elapsed);
  sys_elapsed = sys2.tv_sec + sys2.tv_nsec/1E9;
  sys_elapsed -= sys1.tv_sec + sys1.tv_nsec/1E9;
  printf("CLOCK_PROCESS_CPUTIME_ID: %f\n", sys_elapsed);
}

据我了解,这应该打印类似

CLOCK_REALTIME: 10.000117
CLOCK_PROCESS_CPUTIME_ID: 10.001

但就我而言,我得到的是

CLOCK_REALTIME: 10.000117
CLOCK_PROCESS_CPUTIME_ID: 0.000032

这是正确的行为吗?如果是这样,我如何确定sys1和sys2的实际秒数?

当我将CLOCK_PROCESS_CPUTIME_ID更改为CLOCK_REALTIME时,我得到了预期的结果,但这不是我想要的,因为我们需要精度。

[编辑]显然CLOCK_PROCESS_CPUTIME_ID返回cpu在prcessing上花费的实际时间。 CLOCK_MONOTONIC似乎返回正确的值。但准确度如何?

1 个答案:

答案 0 :(得分:6)

  

基本上我们只需要在几微秒内精确地获取应用程序的当前运行时间。

如果我没有误解,这里的运行时间意味着经过的时间。通常情况下,CLOCK_REALTIME对此有利,但如果在应用程序运行期间设置了时间,则CLOCK_REALTIME的经过时间概念也会发生变化。为了防止这种情况发生 - 不太可能 - 我建议使用CLOCK_MONOTONICCLOCK_MONOTONIC_RAW。从手册页中的描述

   CLOCK_REALTIME
          System-wide real-time clock.  Setting this clock requires appro-
          priate privileges.

   CLOCK_MONOTONIC
          Clock that cannot be set and  represents  monotonic  time  since
          some unspecified starting point.

   CLOCK_MONOTONIC_RAW (since Linux 2.6.28; Linux-specific)
          Similar  to  CLOCK_MONOTONIC, but provides access to a raw hard-
          ware-based time that is not subject to NTP adjustments.

CLOCK_MONOTONIC可能会受到NTP调整的影响,而CLOCK_MONOTONIC_RAW则不会。所有这些时钟通常具有1纳秒的分辨率(使用clock_getres()检查),但为了您的目的,低于1微秒的分辨率就足够了。

以微秒为单位计算经过时间

#define USED_CLOCK CLOCK_MONOTONIC // CLOCK_MONOTONIC_RAW if available
#define NANOS 1000000000LL

int main(int argc, char *argv[]) {
    /* Whatever */
    struct timespec begin, current;
    long long start, elapsed, microseconds;
    /* set up start time data */
    if (clock_gettime(USED_CLOCK, &begin)) {
        /* Oops, getting clock time failed */
        exit(EXIT_FAILURE);
    }
    /* Start time in nanoseconds */
    start = begin.tv_sec*NANOS + begin.tv_nsec;

    /* Do something interesting */

    /* get elapsed time */
    if (clock_gettime(USED_CLOCK, &current)) {
        /* getting clock time failed, what now? */
        exit(EXIT_FAILURE);
    }
    /* Elapsed time in nanoseconds */
    elapsed = current.tv_sec*NANOS + current.tv_nsec - start;
    microseconds = elapsed / 1000 + (elapsed % 1000 >= 500); // round up halves

    /* Display time in microseconds or something */

    return EXIT_SUCCESS;
}