有没有比cpuid更便宜的序列化指令?

问题描述 投票:0回答:4

我已经看到了相关问题,包括herehere,但似乎唯一提到的序列化指令

rdtsc
cpuid

不幸的是,

cpuid
在我的系统上大约需要1000个周期,所以我想知道是否有人知道更便宜的(更少的周期并且不读取或写入内存)序列化指令?

我看了

iret
,但这似乎改变了控制流程,这也是不可取的。

我实际上已经查看了 Alex 关于

rdtscp
的回答中链接的白皮书,但它说:

RDTSCP 指令会等待,直到所有先前的指令都已完成 在读取计数器之前执行。 然而,随后 指令可以在读操作之前开始执行 执行了。

第二点似乎让它不太理想。

assembly x86 intel cpu-cache rdtsc
4个回答
8
投票

您看过

rdtscp
说明了吗?这是
rdtsc
的阅读序列化版本。

对于基准测试,我建议阅读本白皮书。它提供了一些测量时钟滴答声的最佳实践。

亚历克斯(英特尔)


5
投票

订购

rdtsc
wrt。其他说明,如果您不需要等待存储缓冲区耗尽,则
lfence
就足够了。自从一直使用 Intel,自从 Spectre 缓解在 AMD 以来。请参阅rdtsc乱序执行的解决方案?

rdtscp
也保证可以订购。较早的指令(但不是较晚的指令;实际上,它的微编码可能非常类似于
lfence
;
rdtsc
按此顺序,加上用处理器 ID 写入 ECX 的微指令。)它不是 x86 序列化指令,甚至不会耗尽存储缓冲区。 (无论如何,你不一定想要计时。)如果你想要的话,你可以
mfence; rdtscp
lock or byte [rsp], 0 ; rdtscp
,或者
rdtscp; lfence
,如果你想确保它的几个微指令不能与以后的东西一起重新排序。

另请参阅此问答,了解有关 TSC 的更多一般信息,它是固定频率,而不是 CPU 周期。


真正的序列化指令

回答标题中关于 x86 技术术语意义上的“序列化指令”的问题,
Alder Lake(和 Sapphire Rapids)以及后来的

serialize
,它正是这样做的,仅此而已。

lfence
序列化指令执行(耗尽 ROB 但不存储缓冲区或前端):请参阅

在虚拟机中,

cpuid
是有保证的 vmexit,因此速度很慢。推送 RSP、RFLAGS、CS 和 RIP 并运行
iret
指令可能会更快。我没有仔细检查 iret 弹出的内容,因此可能不完全正确。


当您需要真正的序列化指令时

交叉修改代码是一种正确的序列化指令与

mfence
;
lfence
之类的指令相比很重要的情况。在获取加载看到表明新代码存在的发布存储后,您需要运行序列化指令。英特尔第 3 卷手册第 8.1.3 节保证了交叉修改代码的安全性。

我认为这可以确保前端尚未获取旧代码。因此,序列化指令可能会完全破坏管道,或者如果对管道中的最近指令有足够的跟踪来窥探 L1i 失效,则可以执行等效操作。 (这种额外的窥探可能不值得,因为序列化指令很少见。无论如何,都需要跟踪来处理self修改代码,窥探存储地址是否靠近任何正在运行的指令。)

mfence
(或
lock or byte [rsp],0
)+
lfence
不一定足够强大,因为
lfence
仅耗尽ROB,与指令执行有关而不是获取,而
mfence
处理数据加载/存储。如果您无法使用
cpuid
,那么对于这种情况,
serialize
是一个不错的选择。

(即使是写入器中对齐的 8 字节块内的原子 RMW 或原子存储也是不够的。在某些微架构上,我认为从 L1i 缓存中未对齐的 16 字节块代码获取是可能的,因此读者可能会撕裂在任何边界。)


1
投票

答案显然是否定的。 Intel 手册,第 3a 卷 仅列出了 3 个非特权序列化指令(

cpuid
iret
rsm
),后两个似乎具有控制流副作用。


-1
投票

嗯,我想这很有帮助:lfence。参考《64-ia-32-architectures-software-developer-manual》Vol.2B 4-301

© www.soinside.com 2019 - 2024. All rights reserved.