当前位置: 首页 > 面试题库 >

使用RDTSC获取CPU周期-为什么RDTSC的值总是增加?

蒋招
2023-03-14
问题内容

我想在特定时间获取CPU周期。我当时使用此功能:

static __inline__ unsigned long long rdtsc(void)
{
    unsigned long long int x;
    __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
    // broken for 64-bit builds; don't copy this code
    return x;
}

(编者注:"=A"是错的x86-64,捡起 _任何_RDX或RAX仅在32位模式下将它挑EDX:你想EAX输出中看到的。

问题是它总是返回一个 递增的 数字(每次运行)。好像是在指绝对时间。

我使用的功能不正确吗?


问题答案:

只要您的线程停留在相同的CPU内核上,RDTSC指令就会一直返回递增的数字,直到它回绕为止。对于2GHz
CPU,这种情况发生在292年之后,因此这不是一个真正的问题。您可能看不到它的发生。如果您预期寿命如此长,请确保计算机每隔50年重启一次。

RDTSC的问题在于,您不能保证它在旧的多核CPU的所有内核上都在同一时间启动,也不能保证在旧的多CPU板的所有CPU上都在同一时间启动。 。
现代系统通常不会出现此类问题,但是通过设置线程的亲和力使其仅在一个CPU上运行,也可以在较旧的系统上解决该问题。这对应用程序性能不利,因此通常不应该这样做,但是对于刻度线来说,这很好。

(另一个“问题”是,许多人使用RDTSC来测量时间,这 不是 它的工作,但是您写了您想要的CPU周期,这样很好。如果您 确实
使用RDTSC来测量时间,那么当省电,超增压或任何其他频率改变技术都称为踢进。对于实际时间,clock_gettime在Linux下,系统调用非常好。)

我只想rdtscasm语句中写代码,对我来说这很好,并且比一些晦涩的十六进制代码更具可读性。假设它是正确的十六进制代码(并且既然它既不会崩溃也不会返回不断增加的数字,那么看起来是如此),那么您的代码就不错了。

如果要测量一段代码所需要的滴答声数量,则需要滴答声 ,您只需要减去两个不断增加的计数器值即可。喜欢的东西uint64_t t0 = rdtsc(); ... uint64_t t1 = rdtsc() - t0;注意,因为如果从周围的代码分离的非常精确的测量是必要的,你需要序列化,这是失速的管道,调用之前rdtsc(或使用rdtscp其仅支持较新的处理器)。可以在每个特权级别使用的一个序列化指令是cpuid

回答评论中的另一个问题:

当您打开计算机时,TSC从零开始(BIOS重置所有CPU上的所有计数器为相同的值,尽管几年前的某些BIOS不能可靠地将其重置)。

因此,从程序的角度来看,计数器开始于“过去的某个未知时间”,并且总是随着CPU看到的每个时钟滴答而增加。因此,如果您现在和之后的任何时候在不同的过程中执行返回该计数器的指令,它将返回一个更大的值(除非CPU在这之间被挂起或关闭)。同一程序的不同运行次数会增加,因为计数器不断增长。总是。

现在,clock_gettime(CLOCK_PROCESS_CPUTIME_ID)是另一回事了。这是操作系统为进程分配的CPU时间。当您的过程开始时,它从零开始。一个新的过程也从零开始。因此,两个彼此相继运行的进程将获得非常相似或相同的数字,而不是不断增长的数字。

clock_gettime(CLOCK_MONOTONIC_RAW)更接近RDTSC的工作方式(并且在某些旧系统上是用RDTSC实现的)。它返回一个不断增加的值。如今,这通常是HPET。但是,这实际上是
时间 ,而不是 滴答滴答 。如果您的计算机进入低功耗状态(例如,以1/2正常频率运行),它 仍将 以相同的速度前进。



 类似资料:
  • RDTSC 指令的英特尔手册警告说,当 RDTSC 实际执行时,无序执行可能会更改,因此他们建议在其前面插入 CPUID 指令,因为 CPUID 将序列化指令流(CPUID 永远不会无序执行)。我的问题很简单:如果他们有能力进行指令序列化,为什么他们不进行RDTSC序列化?它的全部意义似乎是获得周期准确的时间。是否存在您不希望在它之前使用序列化指令的情况? 较新的英特尔CPU有一个单独的RDTSC

  • 问题内容: 我正在从一个线程发送网络数据包,并收到在不同CPU内核上运行的第二个线程的答复。我的过程测量每个数据包的发送和接收之间的时间(类似于ping)。我正在使用rdtsc来获取高分辨率,低开销的时序,这是我的实现所需的。 所有测量看起来都是可靠的。尽管如此,我仍担心rdtsc在内核之间的准确性,因为我一直在阅读一些文字,这些文章暗示tsc在内核之间不同步。 我在维基百科中找到了有关TSC的以

  • 在最近的CPU上(至少是过去十年左右),Intel提供了三种固定功能硬件性能计数器,此外还有各种可配置的性能计数器。三个固定柜台是: 第一个计算退役的指令,第二个计算实际循环的数量,最后一个计算我们感兴趣的。《英特尔软件开发人员手册》第3卷的描述如下: 当内核不处于停止状态和TM停止时钟状态时,此事件以TSC速率计算参考周期数。内核在运行HLT指令或MWAIT指令时进入halt状态。该事件不受核心

  • 我知道无符号long-long存储在eax/edx中,但我想知道如何找出执行单个rdtsc指令所需的时钟周期? 编辑:像这样的东西有用吗? .GlobalRDTSC rdtsc: rdtsc rdtsc ret

  • 我对ARM Cortex M4组件中的LDR和STR指令有疑问。出于某种原因,它们在内存中写入/读取某些部分比读取其他部分需要更长的时间。 为了说明这一点,我设置了一个简单的示例: 我已经创建了一个项目,它有一个主C文件和一个相邻的。包含汇编代码的文件。我已经使用“extern”对象将汇编函数包含到我的C文件中。 以下是该程序的作用: 它向我们展示了在“register_before_time=A

  • 我现在正在做一个项目,在这个项目中我们使用cucumber-jvm来驱动验收测试。