问题标签 [rdtsc]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
1180 浏览

c - 英特尔的时间戳读取 asm 代码示例是否使用了不必要的两个寄存器?

我正在研究使用 x86 CPU 中的时间戳寄存器 (TSR) 来测量基准性能。这是一个有用的寄存器,因为它以不受时钟速度变化影响的单调时间单位进行测量。很酷。

这是一份英特尔文档,展示了使用 TSR 进行可靠基准测试的 asm 片段,包括使用 cpuid 进行管道同步。见第 16 页:

http://www.intel.com/content/www/us/en/embedded/training/ia-32-ia-64-benchmark-code-execution-paper.html

要阅读开始时间,它会说(我注释了一点):

我想知道为什么使用暂存器来获取edx and的值eaxedx 为什么不删除 mov 并直接从and中读取 TSR 值eax?像这样:

通过这样做,您可以节省两个寄存器,从而降低 C 编译器需要溢出的可能性。

我对吗?还是那些 MOV 具有某种战略意义?

(我同意你确实需要临时寄存器来读取停止时间,因为在那种情况下指令的顺序是相反的:你有 rdtscp,...,cpuid。cpuid 指令破坏了 rdtscp 的结果)。

谢谢

0 投票
3 回答
4848 浏览

c++ - 在具有 constant_tsc 和 nonstop_tsc 的 cpu 上,为什么我的时间会漂移?

我正在使用constant_tsc和的 cpu 上运行此测试nonstop_tsc

第 1 步:计算 tsc 的滴答率:

我计算_ticks_per_ns为多次观察的中位数。我rdtscp用来确保按顺序执行。

第 2 步:计算开始挂钟时间和 tsc

第 3 步:创建一个可以从 tsc 返回挂钟时间的函数

第 4 步:循环运行,从clock_gettime和从打印挂钟时间rdtscp

输出:

问题:

很明显,以这两种方式计算的时间很快就会分开。

我假设tscconstant_tscnonstop_tsc是恒定的。

  • 这是漂移的车载时钟吗?肯定不会以这种速度漂移吗?

  • 这种漂移的原因是什么?

  • 我可以做些什么来使它们保持同步(除了非常频繁地重新计算_start_tsc_start_clock_time在第 2 步中)?

0 投票
2 回答
2302 浏览

c++ - 在 x86_64 平台上是否需要 rdtsc 的 mfence?

mfence在上面的代码中,有必要吗?

根据我的测试,没有找到 cpu reorder。

测试代码片段如下所示。

0 投票
2 回答
12230 浏览

c++ - 使用 rdtsc 计算系统时间

假设我的 CPU 中的所有内核都具有相同的频率,从技术上讲,我可以每毫秒左右同步每个内核的系统时间和时间戳计数器对。然后根据我正在运行的当前核心,我可以采用当前的rdtsc值并使用滴答增量除以核心频率,我能够估计自上次同步系统时间和时间戳计数器对以来经过的时间,并在没有来自当前线程的系统调用开销的情况下推断出当前系统时间(假设检索上述数据不需要锁)。这在理论上很有效,但在实践中我发现有时我得到的滴答声比我预期的要多,也就是说,如果我的核心频率是 1GHz 并且我在 1 毫秒前使用了系统时间和时间戳计数器对,我希望看到一个增量在大约 10^6 刻度的刻度中,但实际上我发现它可以在 10^6 和 10^7 之间的任何地方。我不确定出了什么问题,任何人都可以分享他对如何使用计算系统时间的想法rdtsc? 我的主要目标是避免每次我想知道系统时间时都需要执行系统调用,并且能够在用户空间中执行计算,这将给我一个很好的估计(目前我定义了一个很好的估计结果与实际系统时间相差 10 微秒。

0 投票
1 回答
206 浏览

assembly - RDTSC(分析)NASM 语法

我想计算使用rdtsc指令运行我的程序所需的 CPU 时钟周期,因为它在我的分配中是必需的。在“AFD”
中使用指令的语法应该是什么? 我正在使用指令,但是“AFD”在我的程序执行时终止了它......rdtsc
rdtsc

0 投票
0 回答
732 浏览

c - 如何使用 TSC/RDTSC

我正在尝试测量在我的代码中运行某些函数所花费的时间。由于使用 RDTSC 是最有效的,我想使用它。但是,我无法理解如何实现这一点。

有人可以提供一个示例,说明我们如何在代码(C 语言)中实现这一点并将周期数转换为毫秒?例如,测量读取文件所需的时间。

我找不到关于实现的太多解释,但只找到了定义。

谢谢你。

0 投票
2 回答
613 浏览

c - 跨上下文切换使用 rdtsc + rdtscp

我正在尝试编写一个程序来测量上下文切换。我已经阅读了英特尔关于 rdtsc + rdtscp 指令的手册。

现在,我想在上下文切换中使用这些时间戳指令。我的一般骨架如下:

我在这段代码中看到了一些问题。假设定时器操作是正确的,

如果操作系统选择上下文切换到某个完全不同的进程(不是子进程或父进程),它将无法工作。

此代码还将包括 read() 和 write() 系统调用所花费的时间。

忽略这些问题,是否有效使用 rdtsc + rdtscp 指令?

0 投票
1 回答
643 浏览

c++ - 将 uint64_t rdtsc 值转换为 uint32_t

我有一个 RNG 函数xorshift128plus需要一个Xorshift128PlusKey

我想使用rdtsc(处理器时间戳)播种我的 RNG。问题是__rdtscmsvc 下的内在函数返回一个64 位无符号整数,而种子必须是一个32 位无符号整数在保留随机性的同时将 rdtsc 转换为种子的最佳方法是什么。转换必须尽可能快

我不能使用std libboost。(用于游戏引擎)

0 投票
0 回答
740 浏览

benchmarking - 如何正确使用rdtscp?

根据《How to Benchmark Code Execution Times on Intel® IA-32 and IA-64 Instruction Set Architectures》,我使用以下代码:

但实际上,我也看到有人使用下面的代码:

如您所知,RDTSCP 是伪序列化,为什么有人使用第二个代码?我猜有两个原因,如下:

  • 也许在大多数情况下,RDTSCP 可以确保完整的“按顺序执行”?

  • 也许只是想避免使用 CPUID 来提高效率?

0 投票
1 回答
2919 浏览

performance - 英特尔丢失周期?rdtsc 和 CPU_CLK_UNHALTED.REF_TSC 之间的不一致

在最近的 CPU 上(至少在过去十年左右),除了各种可配置的性能计数器外,英特尔还提供了三个固定功能的硬件性能计数器。三个固定计数器是:

第一个计算退役指令,第二个计算实际周期数,最后一个是我们感兴趣的。英特尔软件开发人员手册第 3 卷的描述是:

当内核未处于停止状态且未处于 TM 停止时钟状态时,此事件以 TSC 速率计算参考周期数。内核在运行 HLT 指令或 MWAIT 指令时进入暂停状态。此事件不受核心频率变化(例如,P 状态)的影响,但以与时间戳计数器相同的频率计数。当内核未处于停止状态且未处于 TM 停止时钟状态时,此事件可以近似于经过的时间。

因此,对于受 CPU 限制的循环,我希望这个值与从 读取的自由运行 TSC 值相同rdstc,因为它们应该只针对暂停的周期指令或“TM 停止时钟状态”是什么而发散。

我使用以下循环测试它(整个独立演示可在 github 上找到):

定时区域中唯一重要的是busy_loop(CALIBRATION_LOOPS);它只是一个易失性存储的紧密循环,它由最近的硬件上的每次迭代编译gccclang执行一个周期:

PFCSTARTandPFCEND命令使用libpfcCPU_CLK_UNHALTED.REF_TSC读取计数器。这是通过指令读取 TSC 的内在函数。最后,我们测量实时时间,简单来说就是:__rdtsc()rdtscnanos()

是的,我没有发出 a cpuid,而且事情并没有以精确的方式交错,但是校准循环是一整秒,所以这种纳秒级的问题只会被稀释到或多或少没有。

启用 TurboBoost 后,以下是在 i7-6700HQ Skylake CPU 上典型运行的前几个结果:

这里,REF_TSC是如上所述的固定 TSC 性能计数器,rdtscrdtsc指令的结果。Eff Mhz是在该时间间隔内有效计算的真实 CPU 频率,主要是出于好奇和快速确认有多少 turbo 正在启动。RatioREF_TSCrdtsc列的比率。我希望这非常接近 1,但实际上我们看到它在 0.90 到 0.92 之间徘徊,并且有很大的差异(我在其他运行中看到它低至 0.8)。

从图形上看,它看起来像这样2

PMU tsc 与 rdstc

rdstc调用返回几乎准确的结果1,而 PMU TSC 计数器无处不在,有时几乎低至 2300 MHz。

但是,如果我关闭 turbo,结果会更加一致:

基本上,该比率是 1.000000 到6 位小数

以图形方式(Y 轴刻度强制与上图相同):

PMU 与 rdtsc(无涡轮增压)

现在代码只是在运行一个热循环,应该没有hltmwait指令,当然没有任何暗示超过 10% 的变化。我不能确定什么是“TM 停止时钟周期”,但我敢打赌它们是“热管理停止时钟周期”,这是一种在达到最高温度时临时限制 CPU 的技巧。然而,我查看了集成热敏电阻的读数,我从来没有看到 CPU 突破 60C,远低于 90C-100C(我认为)。

知道这可能是什么吗?是否存在隐含的“停止周期”来在不同的涡轮频率之间转换?这肯定会发生,因为盒子不是安静的,所以当其他内核开始和停止在后台工作时,涡轮频率会上下跳跃(最大涡轮频率直接取决于活动内核的数量:在我的盒子上是 3.5, 3.3、3.2、3.1 GHz,分别用于 1、2、3 或 4 个活动核心)。


1事实上,有一段时间我确实得到了精确到小数点后两位的结果:2591.97 MHz- 一次又一次的迭代。然后发生了一些变化,我不确定是什么,rdstc结果有大约 0.1% 的小变化。一种可能性是逐步调整时钟,由 Linux 计时子系统进行,以使本地晶体派生时间与ntpd确定的时间一致。也许,它只是一个晶体漂移——上面的最后一张图显示了每秒测量周期的稳定增加rdtsc

2这些图表与文本中显示的值不对应相同的运行,因为我不会在每次更改文本输出格式时更新图表。然而,每次运行的定性行为基本相同。