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

2024-10-18 09:00:00
admin
原创
227
摘要:问题描述:我正在将一个最初为 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)系统以查看实际分辨率是多少。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1325  
  IPD(Integrated Product Development)流程作为一种先进的产品开发管理模式,在众多企业中得到了广泛应用。它涵盖了从产品概念产生到产品退市的整个生命周期,通过整合跨部门团队、优化流程等方式,显著提升产品开发的效率和质量,进而为项目的成功奠定坚实基础。深入探究IPD流程的五个阶段与项目成功之间...
IPD流程分为几个阶段   4  
  华为作为全球知名的科技企业,其成功背后的管理体系备受关注。IPD(集成产品开发)流程作为华为核心的产品开发管理模式,其中的创新管理与实践更是蕴含着丰富的经验和深刻的智慧,对众多企业具有重要的借鉴意义。IPD流程的核心架构IPD流程旨在打破部门墙,实现跨部门的高效协作,将产品开发视为一个整体的流程。它涵盖了从市场需求分析...
华为IPD是什么   3  
  IPD(Integrated Product Development)研发管理体系作为一种先进的产品开发模式,在众多企业的发展历程中发挥了至关重要的作用。它不仅仅是一套流程,更是一种理念,一种能够全方位提升企业竞争力,推动企业持续发展的有效工具。深入探究IPD研发管理体系如何助力企业持续发展,对于众多渴望在市场中立足并...
IPD管理流程   3  
  IPD(Integrated Product Development)流程管理旨在通过整合产品开发流程、团队和资源,实现产品的快速、高质量交付。在这一过程中,有效降低成本是企业提升竞争力的关键。通过优化IPD流程管理中的各个环节,可以在不牺牲产品质量和性能的前提下,实现成本的显著降低,为企业创造更大的价值。优化产品规划...
IPD流程分为几个阶段   4  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

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

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

内置subversion和git源码管理

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

免费试用