Gcc 如何强制CPU在没有任何循环或分支的情况下按顺序执行程序?

Gcc 如何强制CPU在没有任何循环或分支的情况下按顺序执行程序?,gcc,compiler-construction,cpu,cpu-architecture,Gcc,Compiler Construction,Cpu,Cpu Architecture,可能吗?对于没有任何分支/循环的小代码。 对于x86和其他处理器系列,是否有任何gcc标志或内在指令,如SSE?我只是好奇,因为现在所有可用的处理器都遵循无序执行模型 提前感谢大多数现代无序CPU本质上就是无序的,不可能在有序模式和无序模式之间切换 您可以尝试按顺序查找一些CPU,其中有: x86:Intel Atom(仅45 nm及更旧版本;它们有两个并行管道,但按顺序执行所有指令) 臂:皮质A8,和许多旧的核心 虽然在典型的无序CPU中无法直接关闭指令重新排序,但您可以在每一条指令之间插

可能吗?对于没有任何分支/循环的小代码。 对于
x86
和其他处理器系列,是否有任何
gcc
标志或内在指令,如SSE?我只是好奇,因为现在所有可用的处理器都遵循无序执行模型


提前感谢

大多数现代无序CPU本质上就是无序的,不可能在有序模式和无序模式之间切换

您可以尝试按顺序查找一些CPU,其中有:

  • x86:Intel Atom(仅45 nm及更旧版本;它们有两个并行管道,但按顺序执行所有指令)
  • 臂:皮质A8,和许多旧的核心
虽然在典型的无序CPU中无法直接关闭指令重新排序,但您可以在每一条指令之间插入序列化(如x86世界中的
cpuid
)以模拟顺序执行

英特尔手册()中有一部分是关于序列化指令的(复制自):

第3A卷:系统编程指南状态

7.4序列化指令

英特尔64和IA-32体系结构定义了几种串行化 说明书这些指令强制处理器完成所有操作 以前的指令对标志、寄存器和内存的修改 并在下一条指令之前将所有缓冲写入内存 获取并执行。例如,当一个MOV要控制寄存器时 指令用于将新值加载到控制寄存器CR0中,以 启用保护模式时,处理器必须执行序列化 进入保护模式前的操作。这是序列化操作 确保在处理器运行时启动的所有操作 在实地址模式下,在切换到受保护模式之前完成 模式被制作

IA-32中引入了串行化指令的概念 采用奔腾处理器支持并行计算的体系结构 指令执行。序列化指令对用户没有任何意义 Intel486和早期处理器不实现并行 指令执行

需要注意的是,在 P6和更新的处理器系列限制推测执行 因为推测执行指令的结果是 丢弃的。以下说明是序列化说明:

o特权串行化指令-MOV(控制寄存器, 除MOV CR8)、MOV(调试寄存器)、WRMSR、INVD、, INVPG、WBINVD、LGDT、LLDT、LIDT和LTR

o非特权序列化指令-CPUID、IRET和RSM

当处理器序列化指令执行时,它确保 所有挂起的内存事务都已完成(包括写入) 存储在其存储缓冲区中),然后执行下一条指令。 任何东西都不能传递序列化指令和序列化命令 指令不能通过任何其他指令(读、写、, 指令获取(或I/O)。例如,CPUID可以在任何时间执行 序列化指令执行的特权级别,对 程序流,但EAX、EBX、ECX和EDX寄存器 修改


这是可能的,但这取决于CPU。再说一遍,指令本身并不重要,内存访问也很重要

AFAIK all CPU保证寄存器(以及内部状态)按顺序更新,无论执行如何。在一些CPU中,临时寄存器被分配一个值,结果是在适当的时间“写回”(寄存器重命名,因此没有副本本身)

对于内存访问,大多数CPU都有某种内存屏障,这限制了内存访问的重新排序。有几种不同类型的内存屏障,它们因CPU而异。可以想象,在每条指令之间放置一个完整的内存屏障,就可以达到一半。如果您有一台多处理器机器,您可能需要做一些额外的工作,以确保缓存也被刷新。如果没有明确的指示,另一个核心可能无法按顺序看到结果

这在很大程度上取决于您试图实现的目标以及具体的CPU。每个CPU在某些方面都是不同的。而且不会有任何神奇的gcc旗帜。在gcc中,最好的是内置的原子类型(链接如下)。这个话题是巨大的。没有简单的答案

推荐阅读列表:


只需在有序CPU上运行您的代码,如旧版Intel Atom(45nm或更旧)或Cortex-A5或A8 for ARM world(用于ARM world)。在典型的无序CPU中,无法打开或关闭指令重新排序。或者您可以插入序列化的内容(如cpuid)在每一条指令之间模拟顺序执行。@osgx..你能把这作为一个答案吗..NoLept,你的任务是什么?你为什么要按顺序执行?cpuid会减慢所有速度,也会覆盖一半的x86寄存器。@osgx..这只是出于好奇…坦率地说…我会说一些非常规的中断ew问题……除非是一个奇怪的、非一致的多处理器,否则不需要缓存刷新;屏障和一致性确保了内存可见性的有序性。此外,如果监视物理内存访问并期望“有序”活动、预取可能必须被禁用。耶,这是一个混乱,取决于体系结构。在x86/x64上,为了实现内存I/O,您将使用MTRR实现与总线的时间同步。有太多的细节不符合答案。您可以从操作系统开发人员的角度(内存映射IO)来看待它,或应用程序开发人员透视图(线程同步)或算法开发人员