gettimeofday() 能保证达到微秒的分辨率吗?

2024-10-18 09:00:00
admin
原创
69
摘要:问题描述:我正在将一个最初为 Win32 API 编写的游戏移植到 Linux(好吧,将 Win32 端口的 OS X 端口移植到 Linux)。我已经QueryPerformanceCounter通过提供自进程启动以来的 uSeconds 来实现:BOOL QueryPerformanceCounter(L...

问题描述:

我正在将一个最初为 Win32 API 编写的游戏移植到 Linux(好吧,将 Win32 端口的 OS X 端口移植到 Linux)。

我已经QueryPerformanceCounter通过提供自进程启动以来的 uSeconds 来实现:

BOOL QueryPerformanceCounter(LARGE_INTEGER* performanceCount)
{
    gettimeofday(&currentTimeVal, NULL);
    performanceCount->QuadPart = (currentTimeVal.tv_sec - startTimeVal.tv_sec);
    performanceCount->QuadPart *= (1000 * 1000);
    performanceCount->QuadPart += (currentTimeVal.tv_usec - startTimeVal.tv_usec);

    return true;
}

这与QueryPerformanceFrequency()给出一个常数 1000000 作为频率相结合,在我的计算机上uSeconds运行良好,并给了我一个包含自程序启动以来内容的 64 位变量。

那么这可以移植吗?我不想发现如果内核以某种方式编译或类似方式编译,它会有所不同。不过,我可以接受它不能移植到 Linux 以外的其他系统。


解决方案 1:

也许吧。但您有更大的问题。gettimeofday()如果系统上有更改计时器的进程(即 ntpd),则会导致计时不正确。不过,在“普通”Linux 上,我相信的分辨率gettimeofday()是 10us。因此,它可以根据系统上运行的进程向前和向后跳转时间。这实际上使您的问题的答案为否。

您应该查看clock_gettime(CLOCK_MONOTONIC)时间间隔。由于多核系统和外部时钟设置等原因,它遇到的问题较少。

另外,查看clock_getres()函数。

解决方案 2:

适用于英特尔处理器的高分辨率、低开销计时

如果您使用的是 Intel 硬件,以下是读取 CPU 实时指令计数器的方法。它将告诉您自处理器启动以来执行的 CPU 周期数。这可能是您可以获得的性能测量最精细的计数器。

请注意,这是 CPU 周期数。在 Linux 上,您可以从 /proc/cpuinfo 获取 CPU 速度,然后除以得到秒数。将其转换为双精度数非常方便。

当我在我的盒子上运行这个时,我得到了

11867927879484732
11867927879692217
it took this long to call printf: 207485

这是英特尔开发人员指南,其中提供了大量的详细信息。

#include <stdio.h>
#include <stdint.h>

inline uint64_t rdtsc() {
    uint32_t lo, hi;
    __asm__ __volatile__ (
      "xorl %%eax, %%eax
"
      "cpuid
"
      "rdtsc
"
      : "=a" (lo), "=d" (hi)
      :
      : "%ebx", "%ecx");
    return (uint64_t)hi << 32 | lo;
}

main()
{
    unsigned long long x;
    unsigned long long y;
    x = rdtsc();
    printf("%lld
",x);
    y = rdtsc();
    printf("%lld
",y);
    printf("it took this long to call printf: %lld
",y-x);
}

解决方案 3:

@Bernard:

我必须承认,您的大部分示例我都看不懂。不过,它确实可以编译,而且似乎可以工作。这对于 SMP 系统或 SpeedStep 来说安全吗?

这是个好问题……我认为代码没问题。从实际角度来看,我们每天都在公司使用它,并且我们在各种各样的机器上运行,从 2 核到 8 核都有。当然,YMMV 等,但它似乎是一种可靠且低开销(因为它不会将上下文切换到系统空间)的计时方法。

通常它的工作原理是:

  • 将代码块声明为汇编程序(并且是易失性的,因此优化器将不改变它)。

  • 执行 CPUID 指令。除了获取一些 CPU 信息(我们不做任何处理)之外,它还会同步 CPU 的执行缓冲区,这样时序就不会受到无序执行的影响。

  • 执行 rdtsc(读取时间戳)执行。这将获取自处理器重置以来执行的机器周期数。这是一个 64 位值,因此在当前 CPU 速度下,它将每 194 年左右绕回一次。有趣的是,在原始 Pentium 参考中,他们指出它每 5800 年左右绕回一次。

  • 最后几行将寄存器中的值存储到变量 hi 和 lo 中,并将其放入 64 位返回值中。

具体说明:

  • 无序执行会导致不正确的结果,因此我们执行“cpuid”指令,它除了向您提供有关 CPU 的一些信息外,还会同步任何无序指令的执行。

  • 大多数操作系统在启动时都会同步 CPU 上的计数器,因此答案在几纳秒内即可确定。

  • 休眠的评论可能是正确的,但实际上您可能并不关心跨越休眠边界的时间。

  • 关于 speedstep:较新的 Intel CPU 可以补偿速度变化并返回调整后的计数。我快速扫描了我们网络上的一些盒子,发现只有一个盒子没有它:运行一些旧数据库服务器的 Pentium 3。(这些是 Linux 盒子,所以我用 grep constant_tsc /proc/cpuinfo 检查)

  • 我不太清楚 AMD CPU 的情况,我们主要经营英特尔产品,尽管我知道我们的一些低级系统专家做过 AMD 评估。

希望这能满足你的好奇心,这是一个有趣且(在我看来)研究不足的编程领域。你知道 Jeff 和 Joel 当时在谈论程序员是否应该了解 C 语言吗?我冲他们喊道:“嘿,忘掉那些高级 C 语言的东西吧……如果你想知道计算机在做什么,你应该学习汇编语言!”

解决方案 4:

您可能对Linux FAQ感兴趣clock_gettime(CLOCK_REALTIME)

解决方案 5:

Wine 实际上是使用 gettimeofday() 来实现 QueryPerformanceCounter(),并且众所周知它可以使许多 Windows 游戏在 Linux 和 Mac 上运行。

开始http://source.winehq.org/source/dlls/kernel32/cpu.c#L312

指向http://source.winehq.org/source/dlls/ntdll/time.c#L448

解决方案 6:

gettimeofday() 的实际精度取决于硬件架构。Intel 处理器以及 SPARC 计算机提供测量微秒的高精度计时器。其他硬件架构则使用系统计时器,该计时器通常设置为 100 Hz。在这种情况下,时间精度会不太准确。

我从高分辨率时间测量和计时器第一部分获得了这个答案

解决方案 7:

因此它明确指出了微秒,但表示系统时钟的分辨率未指定。我猜想这里的分辨率是指它将增加的最小量是多少?

数据结构定义为以微秒作为测量单位,但这并不意味着时钟或操作系统实际上能够进行精细的测量。

正如其他人所建议的那样,gettimeofday()这很糟糕,因为设置时间可能会导致时钟偏差并影响您的计算。 clock_gettime(CLOCK_MONOTONIC)这就是您想要的,并且clock_getres()会告诉您时钟的精度。

解决方案 8:

这个答案提到了时钟调整的问题。保证滴答单位的问题和调整时间的问题都在 C++11 中通过<chrono>库得到了解决。

该时钟std::chrono::steady_clock保证不会被调整,而且它将相对于实际时间以恒定的速率前进,因此 SpeedStep 等技术一定不会对其产生影响。

您可以通过转换为其中一种std::chrono::duration专业化(例如)来获取类型安全的单位std::chrono::microseconds。使用此类型,刻度值使用的单位不会产生歧义。但是,请记住,时钟不一定具有此分辨率。您可以将持续时间转换为阿秒,而无需实际拥有如此精确的时钟。

解决方案 9:

根据我的经验以及我在网上读到的内容,答案是“否”,这并不能保证。这取决于 CPU 速度、操作系统、Linux 风格等。

解决方案 10:

在 SMP 系统中读取 RDTSC 并不可靠,因为每个 CPU 都维护自己的计数器,并且不能保证每个计数器相对于另一个 CPU 同步。

我可能会建议尝试clock_gettime(CLOCK_REALTIME)。posix 手册指出这应该在所有兼容系统上实现。它可以提供纳秒计数,但您可能需要检查clock_getres(CLOCK_REALTIME)系统以查看实际分辨率是多少。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用