【问题标题】:Clock_gettime nanoseconds calculationClock_gettime 纳秒计算
【发布时间】:2012-12-06 16:21:27
【问题描述】:

参考:linux clock_gettime

我找到了一个可以很好地计算处理时间的公式,但有些东西我不明白。 请看下面的结果。

前 2 行只是在各自的列中显示论坛。

我只显示快速运行的 3 个结果。
有趣的部分在最后一行,为什么5551 - 999896062 nanoseconds = 18446744072709661105?
为什么18446744072709661105+1/1E9 = 0.000109?

我认为正在进行一些影响结果的数据转换?

xx:      | t1.tv_sec |   | t1.tv_nsec |          | t2.tv_sec |   | t2.tv_nsec 
xx:      t2-t1(sec)      t2-t1(nsec)         (t2-t1(sec))+(t2-t1(nsec))/1E9

52291:   | 30437 |   | 999649886 |       | 30437 |   | 999759331 
52291:   0   109445          0.000109

52292:   | 30437 |   | 999772970 |       | 30437 |   | 999882416 
52292:   0   109446          0.000109

52293:   | 30437 |   | 999896062 |       | 30438 |   | 5551 
52293:   1   18446744072709661105        0.000109

源代码:

int main() {
    struct timespec t1, t2;

    int i = 0;
    while(1) {
        clock_gettime(CLOCK_MONOTONIC, &t1);
            for(int j=0;j<25000;j++) { };
        clock_gettime(CLOCK_MONOTONIC, &t2);
        printf("%d: \t | %llu | \t | %lu | \t\t | %llu | \t | %lu \n", i, (unsigned long long) t1.tv_sec, t1.tv_nsec, (unsigned long long) t2.tv_sec, t2.tv_nsec);
        printf("%d: \t %llu \t %lu \t\t %lf\n", i, (unsigned long long) t2.tv_sec - t1.tv_sec, t2.tv_nsec - t1.tv_nsec, (t2.tv_sec - t1.tv_sec)+(t2.tv_nsec - t1.tv_nsec)/1E9);
        if ((t2.tv_sec - t1.tv_sec) == 1) break;
        i++;
    }
    return 0;
}

【问题讨论】:

  • 为什么不将clock_gettime() 的结果转换为64 位的纳秒数呢?让生活变得如此轻松。

标签: c linux profiling


【解决方案1】:

因为 5551 - 999896062 是某个负值,存储在 long 类型的临时变量中,但由于 %lu 转换说明符而被 printf 解释为“unsigned long”。

注意 struct timespec 中的 tv_nsec 字段是 long 类型,而不是 unsigned long。同样,在 Linux 和其他 Unix 系统上,time_t 是有符号整数类型的 typedef。所以去掉你代码中所有未签名的东西。

顺便说一句,减去两个 timespec 实例的方法是


timespec diff(timespec start, timespec end)
{
        timespec temp;
        if ((end.tv_nsec - start.tv_nsec) < 0) 
        {
                temp.tv_sec = end.tv_sec - start.tv_sec - 1;
                temp.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec;
        } 
        else 
        {
                temp.tv_sec = end.tv_sec - start.tv_sec;
                temp.tv_nsec = end.tv_nsec - start.tv_nsec;
        }
        return temp;
}

【讨论】:

  • 我认为您的解决方案是 C++ 解决方案?但无论如何,您对无符号长打印格式是正确的。改变了它,它返回了正确的数字,然后我可以手动验证结果。谢谢。只是好奇,如何验证纳秒精度,因为没有物理介质来测量它。 CLOCK_MONOTONIC 是如何工作的?读到它代表自 1970 年以来的纪元时间。但是如何验证其纳秒精度呢?所有机器都一样吗?
  • @resting:是的,我是从我身边的一些 C++ 代码中复制粘贴的。但是如果你将“timespec”更改为“struct timespec”,它也应该可以在纯 C 中工作。
  • @resting: CLOCK_MONOTONIC 表示自过去某个未指定时间以来的时间(例如,在 Linux 上,零设置为系统启动时间之前的某个时间),并且是单调的,即不会改变,例如如果系统时钟改变。 CLOCK_REALTIME 表示自纪元以来的时间。
  • @UserNotDefined: tv_nsec 是小数秒,即自 tv_sec 字段中的整秒以来的纳秒。
  • @john 因为字段tv_sec可能不一样,这样两个字段(tv_nsec)相减的结果就有可能为负。
猜你喜欢
  • 1970-01-01
  • 2023-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-17
  • 1970-01-01
  • 2011-05-17
相关资源
最近更新 更多